From 71de35489e8cf505687a550f8fe9b634b2072553 Mon Sep 17 00:00:00 2001 From: Yogeshwar Srikrishnan Date: Thu, 2 Jun 2011 17:19:45 -0500 Subject: Support transforming service catalog --- keystone/logic/types/auth.py | 49 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) mode change 100644 => 100755 keystone/logic/types/auth.py diff --git a/keystone/logic/types/auth.py b/keystone/logic/types/auth.py old mode 100644 new mode 100755 index b010eea5..fcf72a3c --- a/keystone/logic/types/auth.py +++ b/keystone/logic/types/auth.py @@ -119,8 +119,12 @@ class User(object): class AuthData(object): "Authentation Information returned upon successful login." - def __init__(self, token): + def __init__(self, token, base_urls = None): self.token = token + self.base_urls = base_urls + self.d = {} + if base_urls != None: + self.__convert_baseurls_to_dict() def to_xml(self): dom = etree.Element("auth", @@ -129,7 +133,33 @@ class AuthData(object): expires=self.token.expires.isoformat()) token.set("id", self.token.token_id) dom.append(token) + if base_urls != None: + service_catalog = etree.Element("serviceCatalog") + for key, key_base_urls in self.d.items(): + service = etree.Element("service", + name = key) + for base_url in key_base_urls: + endpoint = etree.Element("endpoint") + if base_url.region: + endpoint.set("region", base_url.region) + if base_url.public_url: + endpoint.set("publicURL", base_url.public_url) + if base_url.admin_url: + endpoint.set("adminURL", base_url.admin_url) + if base_url.internal_url: + endpoint.set("internalURL", base_url.internal_url) + service.append(endpoint) + service_catalog.append(service) + dom.append(service_catalog) return etree.tostring(dom) + + def __convert_baseurls_to_dict(self): + print self.base_urls + for base_url in self.base_urls: + if base_url.service not in self.d: + self.d[base_url.service] = list() + self.d[base_url.service].append(base_url) + print self.d def to_json(self): token = {} @@ -137,6 +167,23 @@ class AuthData(object): token["expires"] = self.token.expires.isoformat() auth = {} auth["token"] = token + if base_urls != None: + service_catalog = {} + for key, key_base_urls in self.d.items(): + endpoints = [] + for base_url in key_base_urls: + endpoint = {} + if base_url.region: + endpoint["region"] = base_url.region + if base_url.public_url: + endpoint["publicURL"] = base_url.public_url + if base_url.admin_url: + endpoint["adminURL"] = base_url.admin_url + if base_url.internal_url: + endpoint["internalURL"] = base_url.internal_url + endpoints.append(endpoint) + service_catalog[key] = endpoints + auth["serviceCatalog"] = service_catalog ret = {} ret["auth"] = auth return json.dumps(ret) -- cgit From 25c3e9cb648bbb89aca81b9c341383a5a8b87a96 Mon Sep 17 00:00:00 2001 From: Yogeshwar Srikrishnan Date: Fri, 3 Jun 2011 12:12:50 -0500 Subject: Changes to support service catalog. --- keystone/db/sqlalchemy/api.py | 11 ++++++++++- keystone/logic/service.py | 5 ++--- keystone/logic/types/auth.py | 21 ++++++++++----------- test/unit/test_authentication.py | 20 ++++++++++++++++++++ 4 files changed, 42 insertions(+), 15 deletions(-) mode change 100644 => 100755 test/unit/test_authentication.py diff --git a/keystone/db/sqlalchemy/api.py b/keystone/db/sqlalchemy/api.py index 5a60eef8..8e15ae26 100644 --- a/keystone/db/sqlalchemy/api.py +++ b/keystone/db/sqlalchemy/api.py @@ -1162,4 +1162,13 @@ def baseurls_ref_delete(id, session=None): with session.begin(): baseurls_ref = baseurls_ref_get(id, session) session.delete(baseurls_ref) - \ No newline at end of file + +def tenant_baseurls_get_all(tenant_id, session=None): + if not session: + session = get_session() + tba = aliased(models.TenantBaseURLAssociation) + baseUrls = aliased(models.BaseUrls) + return session.query(baseUrls).join((tba, tba.baseURLs_id == baseUrls.id)).\ + filter(tba.tenant_id == tenant_id).all() + + \ No newline at end of file diff --git a/keystone/logic/service.py b/keystone/logic/service.py index 43b45e12..996b392c 100755 --- a/keystone/logic/service.py +++ b/keystone/logic/service.py @@ -839,10 +839,9 @@ class IdentityService(object): def __get_auth_data(self, dtoken): """return AuthData object for a token""" - + base_urls = db_api.tenant_baseurls_get_all(dtoken.tenant_id) token = auth.Token(dtoken.expires, dtoken.token_id, dtoken.tenant_id) - - return auth.AuthData(token) + return auth.AuthData(token, base_urls) def __get_validate_data(self, dtoken, duser): """return ValidateData object for a token/user pair""" diff --git a/keystone/logic/types/auth.py b/keystone/logic/types/auth.py index fcf72a3c..36656547 100755 --- a/keystone/logic/types/auth.py +++ b/keystone/logic/types/auth.py @@ -123,7 +123,7 @@ class AuthData(object): self.token = token self.base_urls = base_urls self.d = {} - if base_urls != None: + if self.base_urls != None: self.__convert_baseurls_to_dict() def to_xml(self): @@ -133,7 +133,7 @@ class AuthData(object): expires=self.token.expires.isoformat()) token.set("id", self.token.token_id) dom.append(token) - if base_urls != None: + if self.base_urls != None: service_catalog = etree.Element("serviceCatalog") for key, key_base_urls in self.d.items(): service = etree.Element("service", @@ -143,18 +143,17 @@ class AuthData(object): if base_url.region: endpoint.set("region", base_url.region) if base_url.public_url: - endpoint.set("publicURL", base_url.public_url) + endpoint.set("publicURL", base_url.public_url.replace('%tenant_id%',self.token.tenant_id)) if base_url.admin_url: - endpoint.set("adminURL", base_url.admin_url) + endpoint.set("adminURL", base_url.admin_url.replace('%tenant_id%',self.token.tenant_id)) if base_url.internal_url: - endpoint.set("internalURL", base_url.internal_url) + endpoint.set("internalURL", base_url.internal_url.replace('%tenant_id%',self.token.tenant_id)) service.append(endpoint) service_catalog.append(service) dom.append(service_catalog) return etree.tostring(dom) def __convert_baseurls_to_dict(self): - print self.base_urls for base_url in self.base_urls: if base_url.service not in self.d: self.d[base_url.service] = list() @@ -167,20 +166,20 @@ class AuthData(object): token["expires"] = self.token.expires.isoformat() auth = {} auth["token"] = token - if base_urls != None: + if self.base_urls != None: service_catalog = {} for key, key_base_urls in self.d.items(): endpoints = [] for base_url in key_base_urls: endpoint = {} if base_url.region: - endpoint["region"] = base_url.region + endpoint["region"] = base_url.region if base_url.public_url: - endpoint["publicURL"] = base_url.public_url + endpoint["publicURL"] = base_url.public_url.replace('%tenant_id%',self.token.tenant_id) if base_url.admin_url: - endpoint["adminURL"] = base_url.admin_url + endpoint["adminURL"] = base_url.admin_url.replace('%tenant_id%',self.token.tenant_id) if base_url.internal_url: - endpoint["internalURL"] = base_url.internal_url + endpoint["internalURL"] = base_url.internal_url.replace('%tenant_id%',self.token.tenant_id) endpoints.append(endpoint) service_catalog[key] = endpoints auth["serviceCatalog"] = service_catalog diff --git a/test/unit/test_authentication.py b/test/unit/test_authentication.py old mode 100644 new mode 100755 index 16160d48..301644d5 --- a/test/unit/test_authentication.py +++ b/test/unit/test_authentication.py @@ -47,6 +47,13 @@ class AuthenticationTest(unittest.TestCase): def test_a_authorize(self): resp, content = utils.get_token('joeuser', 'secrete', self.tenant) self.assertEqual(200, int(resp['status'])) + obj = content + if not "auth" in obj: + raise fault.BadRequestFault("Expecting Auth") + auth = obj["auth"] + if not "serviceCatalog" in auth: + raise fault.BadRequestFault("Expecting Service Catalog") + self.assertEqual('application/json', utils.content_type(resp)) def test_a_authorize_xml(self): @@ -54,6 +61,19 @@ class AuthenticationTest(unittest.TestCase): self.tenant) self.assertEqual(200, int(resp['status'])) self.assertEqual('application/xml', utils.content_type(resp)) + + #verify content + dom = etree.Element("root") + dom.append(etree.fromstring(content)) + auth = dom.find("{http://docs.openstack.org/identity/api/v2.0}" \ + "auth") + if auth == None: + self.fail("Expecting Auth") + service_catalog = auth.find("{http://docs.openstack.org/identity/api/v2.0}" \ + "serviceCatalog") + if service_catalog == None: + self.fail("Expecting Service Catalog") + def test_a_authorize_legacy(self): resp, content = utils.get_token_legacy('joeuser', 'secrete') -- cgit From 5b78f2543a563d2b19f76690b15a3c08bad5ec77 Mon Sep 17 00:00:00 2001 From: Yogeshwar Srikrishnan Date: Fri, 3 Jun 2011 12:32:46 -0500 Subject: Updating tests and sample data. --- bin/sampledata.sh | 4 ++-- test/unit/test_authentication.py | 3 +++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/bin/sampledata.sh b/bin/sampledata.sh index 47fa21f7..934e898b 100755 --- a/bin/sampledata.sh +++ b/bin/sampledata.sh @@ -40,8 +40,8 @@ #BaseURLs ./keystone-manage $* baseURLs add DFW cloudFiles public.cloudfiles.com admin.cloudfiles.com internal.cloudfiles.com 1 #v1.0 URLs -./keystone-manage $* baseURLs add DFW X-Storage-Url https://storage.clouddrive.com/v1/%tenant_id% https://storage.clouddrive.com/v1/%tenant_id% https://storage.clouddrive.com/v1/%tenant_id% 1 -./keystone-manage $* baseURLs add DFW X-Server-Management-Url https://servers.api.rackspacecloud.com/v1.0/%tenant_id% https://servers.api.rackspacecloud.com/v1.0/%tenant_id% https://servers.api.rackspacecloud.com/v1.0/%tenant_id% 1 +./keystone-manage $* baseURLs add DFW cloudFilesCDN https://storage.clouddrive.com/v1/%tenant_id% https://storage.clouddrive.com/v1/%tenant_id% https://storage.clouddrive.com/v1/%tenant_id% 1 +./keystone-manage $* baseURLs add DFW cloudServers https://servers.api.rackspacecloud.com/v1.0/%tenant_id% https://servers.api.rackspacecloud.com/v1.0/%tenant_id% https://servers.api.rackspacecloud.com/v1.0/%tenant_id% 1 # Groups #./keystone-manage $* group add Admin 1234 diff --git a/test/unit/test_authentication.py b/test/unit/test_authentication.py index 301644d5..a373d9a4 100755 --- a/test/unit/test_authentication.py +++ b/test/unit/test_authentication.py @@ -38,10 +38,13 @@ class AuthenticationTest(unittest.TestCase): #self.user = utils.get_user() self.userdisabled = utils.get_userdisabled() self.auth_token = utils.get_auth_token() + utils.create_baseurls_ref(self.tenant,"1", + str(self.auth_token)) #self.exp_auth_token = utils.get_exp_auth_token() #self.disabled_token = utils.get_disabled_token() def tearDown(self): + utils.delete_all_baseurls_ref(self.tenant, self.auth_token) utils.delete_token(self.token, self.auth_token) def test_a_authorize(self): -- cgit From f5d64f9b6a8bd0f185a7ce4d626476bfd1149a3e Mon Sep 17 00:00:00 2001 From: Yogeshwar Srikrishnan Date: Fri, 3 Jun 2011 14:31:02 -0500 Subject: Changes to return service urls for Auth1.0 style calls. --- bin/sampledata.sh | 3 +-- keystone/logic/service.py | 20 ++++++++++++++------ keystone/logic/types/auth.py | 1 - keystone/server.py | 33 +++++++++++++++++++++++++++++++++ test/unit/test_authentication.py | 8 ++++++++ 5 files changed, 56 insertions(+), 9 deletions(-) mode change 100644 => 100755 keystone/server.py diff --git a/bin/sampledata.sh b/bin/sampledata.sh index 934e898b..0238d36b 100755 --- a/bin/sampledata.sh +++ b/bin/sampledata.sh @@ -39,9 +39,8 @@ #BaseURLs ./keystone-manage $* baseURLs add DFW cloudFiles public.cloudfiles.com admin.cloudfiles.com internal.cloudfiles.com 1 -#v1.0 URLs ./keystone-manage $* baseURLs add DFW cloudFilesCDN https://storage.clouddrive.com/v1/%tenant_id% https://storage.clouddrive.com/v1/%tenant_id% https://storage.clouddrive.com/v1/%tenant_id% 1 -./keystone-manage $* baseURLs add DFW cloudServers https://servers.api.rackspacecloud.com/v1.0/%tenant_id% https://servers.api.rackspacecloud.com/v1.0/%tenant_id% https://servers.api.rackspacecloud.com/v1.0/%tenant_id% 1 +./keystone-manage $* baseURLs add DFW cloudServers https://servers2.api.rackspacecloud.com/v1.0/%tenant_id% https://servers.api.rackspacecloud.com/v1.0/%tenant_id% https://servers.api.rackspacecloud.com/v1.0/%tenant_id% 1 # Groups #./keystone-manage $* group add Admin 1234 diff --git a/keystone/logic/service.py b/keystone/logic/service.py index 745ceeff..ac46db8d 100755 --- a/keystone/logic/service.py +++ b/keystone/logic/service.py @@ -64,17 +64,23 @@ class IdentityService(object): else: dtoken = db_api.token_for_user_tenant(duser.id, credentials.tenant_id) + tenant_id = None + if credentials.tenant_id: + tenant_id = credentials.tenant_id + else: + tenant_id = duser.tenant_id + if not dtoken or dtoken.expires < datetime.now(): # Create new token dtoken = db_models.Token() dtoken.token_id = str(uuid.uuid4()) dtoken.user_id = duser.id if credentials.tenant_id: - dtoken.tenant_id = credentials.tenant_id + tenant_id = credentials.tenant_id dtoken.expires = datetime.now() + timedelta(days=1) db_api.token_create(dtoken) - - return self.__get_auth_data(dtoken) + #if tenant_id is passed in the call that tenant_id is passed else user's default tenant_id is used. + return self.__get_auth_data(dtoken, tenant_id) def validate_token(self, admin_token, token_id, belongs_to=None): self.__validate_token(admin_token) @@ -838,10 +844,12 @@ class IdentityService(object): # - def __get_auth_data(self, dtoken): + def __get_auth_data(self, dtoken, tenant_id): """return AuthData object for a token""" - base_urls = db_api.tenant_baseurls_get_all(dtoken.tenant_id) - token = auth.Token(dtoken.expires, dtoken.token_id, dtoken.tenant_id) + base_urls = None + if tenant_id != None: + base_urls = db_api.tenant_baseurls_get_all(tenant_id) + token = auth.Token(dtoken.expires, dtoken.token_id, tenant_id) return auth.AuthData(token, base_urls) def __get_validate_data(self, dtoken, duser): diff --git a/keystone/logic/types/auth.py b/keystone/logic/types/auth.py index 49590748..804a8841 100755 --- a/keystone/logic/types/auth.py +++ b/keystone/logic/types/auth.py @@ -159,7 +159,6 @@ class AuthData(object): if base_url.service not in self.d: self.d[base_url.service] = list() self.d[base_url.service].append(base_url) - print self.d def to_json(self): token = {} diff --git a/keystone/server.py b/keystone/server.py old mode 100644 new mode 100755 index fd4b50d7..b306a195 --- a/keystone/server.py +++ b/keystone/server.py @@ -203,6 +203,39 @@ class LegacyAuthController(wsgi.Controller): result = service.authenticate(creds) headers = {"X-Auth-Token": result.token.token_id} + server_urls = '' + files_urls = '' + files_cdn_urls = '' + if result.base_urls != None: + for base_url in result.base_urls: + if base_url.service == 'cloudServers': + if base_url.public_url: + if(len(server_urls) > 0): + server_urls += ',' + server_urls += base_url.public_url.replace('%tenant_id%', result.token.tenant_id) + + if base_url.service == 'cloudFiles': + if base_url.public_url: + if(len(files_urls) > 0): + files_urls += ',' + files_urls += base_url.public_url.replace('%tenant_id%', result.token.tenant_id) + + if base_url.service == 'cloudFilesCDN': + if base_url.public_url: + if(len(files_cdn_urls) > 0): + files_cdn_urls += ',' + files_cdn_urls += base_url.public_url.replace('%tenant_id%', result.token.tenant_id) + + + if len(server_urls) > 0: + headers["X-Server-Management-Url"] = server_urls + + if len(files_urls) > 0: + headers["X-Storage-Url"] = files_urls + + if len(files_cdn_urls) > 0: + headers["X-CDN-Management-Url"] = files_cdn_urls + return utils.send_legacy_result(204, headers) diff --git a/test/unit/test_authentication.py b/test/unit/test_authentication.py index a373d9a4..9a25a2d7 100755 --- a/test/unit/test_authentication.py +++ b/test/unit/test_authentication.py @@ -39,7 +39,11 @@ class AuthenticationTest(unittest.TestCase): self.userdisabled = utils.get_userdisabled() self.auth_token = utils.get_auth_token() utils.create_baseurls_ref(self.tenant,"1", + str(self.auth_token)) + utils.create_baseurls_ref(self.tenant,"2", str(self.auth_token)) + utils.create_baseurls_ref(self.tenant,"3", + str(self.auth_token)) #self.exp_auth_token = utils.get_exp_auth_token() #self.disabled_token = utils.get_disabled_token() @@ -82,6 +86,10 @@ class AuthenticationTest(unittest.TestCase): resp, content = utils.get_token_legacy('joeuser', 'secrete') self.assertEqual(204, int(resp['status'])) self.assertTrue(resp['x-auth-token']) + self.assertTrue(resp['x-server-management-url']) + self.assertTrue(resp['x-storage-url']) + self.assertTrue(resp['x-cdn-management-url']) + print resp['x-server-management-url'] def test_a_authorize_user_disabled(self): header = httplib2.Http(".cache") -- cgit From 0db9cef9269ac06d5b7bef8ff5e4badea384948e Mon Sep 17 00:00:00 2001 From: Yogeshwar Srikrishnan Date: Fri, 3 Jun 2011 14:37:37 -0500 Subject: Changes to return service urls for Auth1.0 style calls. --- keystone/logic/service.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/keystone/logic/service.py b/keystone/logic/service.py index ac46db8d..69875b00 100755 --- a/keystone/logic/service.py +++ b/keystone/logic/service.py @@ -76,7 +76,7 @@ class IdentityService(object): dtoken.token_id = str(uuid.uuid4()) dtoken.user_id = duser.id if credentials.tenant_id: - tenant_id = credentials.tenant_id + dtoken.tenant_id = credentials.tenant_id dtoken.expires = datetime.now() + timedelta(days=1) db_api.token_create(dtoken) #if tenant_id is passed in the call that tenant_id is passed else user's default tenant_id is used. -- cgit From d415e9d00e3a49b0a5dca27c724b56daa7870a6f Mon Sep 17 00:00:00 2001 From: Yogeshwar Srikrishnan Date: Fri, 3 Jun 2011 14:47:37 -0500 Subject: Removing debug print --- test/unit/test_authentication.py | 1 - 1 file changed, 1 deletion(-) diff --git a/test/unit/test_authentication.py b/test/unit/test_authentication.py index 9a25a2d7..a1751c5e 100755 --- a/test/unit/test_authentication.py +++ b/test/unit/test_authentication.py @@ -89,7 +89,6 @@ class AuthenticationTest(unittest.TestCase): self.assertTrue(resp['x-server-management-url']) self.assertTrue(resp['x-storage-url']) self.assertTrue(resp['x-cdn-management-url']) - print resp['x-server-management-url'] def test_a_authorize_user_disabled(self): header = httplib2.Http(".cache") -- cgit From c41fab4e8baaef735b4d29560eb0871284a90735 Mon Sep 17 00:00:00 2001 From: Yogeshwar Srikrishnan Date: Wed, 8 Jun 2011 01:20:48 -0500 Subject: Introducing new frontend component to handle rackspace legacy calls. --- bin/rackspace-keystone | 104 ++++++++++++++++++ keystone/common/config.py | 12 ++- keystone/frontends/__init__.py | 0 keystone/frontends/rackspace_legacy_auth.py | 160 ++++++++++++++++++++++++++++ 4 files changed, 271 insertions(+), 5 deletions(-) create mode 100755 bin/rackspace-keystone mode change 100644 => 100755 keystone/common/config.py create mode 100644 keystone/frontends/__init__.py create mode 100755 keystone/frontends/rackspace_legacy_auth.py diff --git a/bin/rackspace-keystone b/bin/rackspace-keystone new file mode 100755 index 00000000..7dd20697 --- /dev/null +++ b/bin/rackspace-keystone @@ -0,0 +1,104 @@ +#!/usr/bin/env python +# vim: tabstop=4 shiftwidth=4 softtabstop=4 + +# Copyright 2010 United States Government as represented by the +# Administrator of the National Aeronautics and Space Administration. +# Copyright 2011 OpenStack LLC. +# All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may +# not use this file except in compliance with the License. You may obtain +# a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations +# under the License. + +""" +Keystone Identity Server - Admin and Service API +""" + +import optparse +import os +import sys + +# If ../../keystone/__init__.py exists, add ../ to Python search path, so that +# it will override what happens to be installed in /usr/(local/)lib/python... +possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]), + os.pardir, + os.pardir)) +if os.path.exists(os.path.join(possible_topdir, 'keystone', '__init__.py')): + sys.path.insert(0, possible_topdir) + +import tools.tracer #load this first +import keystone +from keystone.common import config +from keystone.common import wsgi + + +if __name__ == '__main__': + # Initialize a parser for our configuration paramaters + parser = optparse.OptionParser(version='%%prog %s' % keystone.version) + common_group = config.add_common_options(parser) + config.add_log_options(parser) + + # Handle a special argument to support starting two endpoints + common_group.add_option('-a', '--admin-port', default=8081, + dest="admin_port", metavar="PORT", + help = "specifies port for Admin API to listen" + "on (default is 8081)") + + common_group.add_option('-r', '--rackspace-legacy-port', default=8082, + dest="rackspace_legacy_port", metavar="PORT", + help = "specifies port for Rackspace Legacy API to listen" + "on (default is 8082)") + + # Parse arguments and load config + (options, args) = config.parse_options(parser) + + # Start services + try: + # Load Service API server + conf, app = config.load_paste_app('server', options, args) + + debug = options.get('debug') or conf.get('debug', False) + debug = debug in [True, "True", "1"] + verbose = options.get('verbose') or conf.get('verbose', False) + verbose = verbose in [True, "True", "1"] + if debug or verbose: + config_file = config.find_config_file(options, args) + print "Using config file:", config_file + + server = wsgi.Server() + server.start(app, int(conf['bind_port']), conf['bind_host']) + print "Service API listening on %s:%s" % (conf['bind_host'], + conf['bind_port']) + + # Load Admin API server + admin_conf, admin_app = config.load_paste_app('admin', options, args) + admin_server = wsgi.Server() + admin_bind = options.get('admin_port') or admin_conf.get('bind_port') + if conf['bind_port'] == admin_bind: + admin_bind += 1 + admin_server.start(admin_app, int(admin_bind), + admin_conf['bind_host']) + print "Admin API listening on %s:%s" % (admin_conf['bind_host'], + admin_bind) + + #Load Rackspace Legacy API + options['config_file'] = 'rackspace_legacy_auth.conf' + print options.get('config_file') + conf, app = config.load_paste_app('rackspace_legacy_auth', options, args) + server = wsgi.Server() + server.start(app, int(conf['bind_port']), conf['bind_host']) + print "Rackspace Legacy Service API listening on %s:%s" % (conf['bind_host'], + conf['bind_port']) + + # Wait until done + server.wait() + except RuntimeError, e: + sys.exit("ERROR: %s" % e) diff --git a/keystone/common/config.py b/keystone/common/config.py old mode 100644 new mode 100755 index 34281192..ed8cb228 --- a/keystone/common/config.py +++ b/keystone/common/config.py @@ -227,7 +227,7 @@ def find_config_file(options, args): We search for the paste config file in the following order: * If --config-file option is used, use that * If args[0] is a file, use that - * Search for keystone.conf in standard directories: + * Search for config file in standard directories: * . * ~.keystone/ * ~ @@ -242,14 +242,16 @@ def find_config_file(options, args): os.pardir, os.pardir)) fix_path = lambda p: os.path.abspath(os.path.expanduser(p)) + file_name = 'keystone.conf' if options.get('config_file'): + file_name = options.get('config_file') if os.path.exists(options['config_file']): return fix_path(options['config_file']) elif args: if os.path.exists(args[0]): return fix_path(args[0]) - # Handle standard directory search for keystone.conf + # Handle standard directory search for keystone.conf or passed conf file. config_file_dirs = [fix_path(os.getcwd()), fix_path(os.path.join('~', '.keystone')), fix_path('~'), @@ -257,15 +259,15 @@ def find_config_file(options, args): '/etc'] for cfg_dir in config_file_dirs: - cfg_file = os.path.join(cfg_dir, 'keystone.conf') + cfg_file = os.path.join(cfg_dir, file_name) if os.path.exists(cfg_file): return cfg_file else: if os.path.exists(os.path.join(POSSIBLE_TOPDIR, 'etc', \ - 'keystone.conf')): + file_name)): # For debug only config_file = os.path.join(POSSIBLE_TOPDIR, 'etc', \ - 'keystone.conf') + file_name) return config_file diff --git a/keystone/frontends/__init__.py b/keystone/frontends/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/keystone/frontends/rackspace_legacy_auth.py b/keystone/frontends/rackspace_legacy_auth.py new file mode 100755 index 00000000..359aaf13 --- /dev/null +++ b/keystone/frontends/rackspace_legacy_auth.py @@ -0,0 +1,160 @@ +#!/usr/bin/env python +# vim: tabstop=4 shiftwidth=4 softtabstop=4 +# +# Copyright (c) 2010-2011 OpenStack, LLC. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# Not Yet PEP8 standardized + + +""" +RACKSPACE LEGACY AUTH - STUB + +This WSGI component +- collects, transforms and forwards identity information from the keystone authentication process + into rackspace specific format. +""" +import os +import sys +import routes +import eventlet +import optparse +import httplib2 +import json +import ast + +from webob import Response +from paste.deploy import loadapp +from webob.exc import HTTPUnauthorized, HTTPInternalServerError + +POSSIBLE_TOPDIR = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]), + os.pardir, + os.pardir, + os.pardir)) +if os.path.exists(os.path.join(POSSIBLE_TOPDIR, 'keystone', '__init__.py')): + sys.path.insert(0, POSSIBLE_TOPDIR) + +import keystone +import keystone.utils as utils +from keystone.common import wsgi +from keystone.common import config + +class RackspaceLegacyAuthController(wsgi.Controller): + """ + Auth Controller for v1.x - + Controller for token related operations + """ + + def __init__(self, options): + self.options = options + self.request = None + # where to find the auth service (we use this to validate tokens) + self.auth_host = options.get('auth_host') + self.auth_port = int(options.get('auth_port')) + self.auth_protocol = options.get('auth_protocol', 'https') + self.auth_location = "%s://%s:%s" % (self.auth_protocol, + self.auth_host, + self.auth_port) + + @utils.wrap_error + def authenticate(self, req): + header = httplib2.Http(".cache") + self.request = req + + url = '%s/v2.0/tokens' % self.auth_location + + body = {"passwordCredentials": {"username": utils.get_auth_user(self.request), + "password": utils.get_auth_key(self.request)}} + + resp, content = header.request(url, "POST", body=json.dumps(body), + headers={"Content-Type": "application/json"}) + + if int(resp['status']) != 200: + response = Response() + response.status = resp.status + response.reason = resp.reason + return response + + content = json.loads(content) + + headers = {} + + if "auth" in content: + auth = content["auth"] + + if "token" in auth: + headers["X-Auth-Token"] = auth["token"]["id"] + + if "serviceCatalog" in auth: + services = auth["serviceCatalog"] + service_mappings = ast.literal_eval(self.options["service-header-mappings"]) + for service in services: + service_name = service + service_urls = '' + for endpoint in services[service_name]: + if len(service_urls) > 0: + service_urls += ',' + service_urls += endpoint["publicURL"] + if len(service_urls) > 0: + if service_mappings.get(service_name): + headers[service_mappings.get(service_name)] = service_urls + else: + #For Services that are not mapped user X- prefix followed by service name. + headers['X-' + service_name.upper()] = service_urls + return utils.send_legacy_result(204, headers) + +class RackspaceLegacyAuthenticator(wsgi.Router): + """Rackspace Legacy Protocol that handles authenticating client calls made in Rackspace format.""" + + def __init__(self, options): + self.options = options + mapper = routes.Mapper() + # Legacy Token Operations + legacy_auth_controller = RackspaceLegacyAuthController(options) + mapper.connect("/v1.0", controller=legacy_auth_controller, + action="authenticate") + mapper.connect("/v1.0/", controller=legacy_auth_controller, + action="authenticate") + mapper.connect("/v1.1/tokens", controller=legacy_auth_controller, + action="authenticate", + conditions=dict(method=["POST"])) + mapper.connect("/v1.1/tokens/", controller=legacy_auth_controller, + action="authenticate", + conditions=dict(method=["POST"])) + super(RackspaceLegacyAuthenticator, self).__init__(mapper) + +def app_factory(global_conf, ** local_conf): + conf = global_conf.copy() + conf.update(local_conf) + return RackspaceLegacyAuthenticator(conf) + +if __name__ == "__main__": + expected_options = {'verbose': False, 'debug': False, + 'config_file': 'rackspace_legacy_auth.conf'} + + parser = optparse.OptionParser(version='%%prog %s' % keystone.version) + # Parse arguments and load config + (options, args) = config.parse_options(parser) + # Start services + try: + conf, app = config.load_paste_app('rackspace_legacy_auth', expected_options, args) + server = wsgi.Server() + server.start(app, int(conf['bind_port']), conf['bind_host']) + print "Rackspace Legacy Service API listening on %s:%s" % (conf['bind_host'], + conf['bind_port']) + server.wait() + + except RuntimeError, e: + sys.exit("ERROR: %s" % e) + -- cgit From c41da0a6a7b5b9df491442f1361160193f67d217 Mon Sep 17 00:00:00 2001 From: Yogeshwar Srikrishnan Date: Wed, 8 Jun 2011 01:21:22 -0500 Subject: Introducing new frontend component to handle rackspace legacy calls. --- etc/rackspace_legacy_auth.conf | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 etc/rackspace_legacy_auth.conf diff --git a/etc/rackspace_legacy_auth.conf b/etc/rackspace_legacy_auth.conf new file mode 100644 index 00000000..e8a8cbd8 --- /dev/null +++ b/etc/rackspace_legacy_auth.conf @@ -0,0 +1,17 @@ +[DEFAULT] + +[app:rackspace_legacy_auth] +paste.app_factory = keystone.frontends.rackspace_legacy_auth:app_factory + +# Keystone Service Details +auth_host = 127.0.0.1 +auth_port = 8081 +auth_protocol = http + +# Address to bind the API server +bind_host = 0.0.0.0 + +# Port the bind the API server to +bind_port = 8082 + +service-header-mappings = {'cloudServers' : 'X-Server-Management-Url' , 'cloudFiles' : 'X-Storage-Url', 'cloudFilesCDN' : 'X-CDN-Management-Url'} \ No newline at end of file -- cgit From fb50f8aa036d9fe7823f18033518676f0370f967 Mon Sep 17 00:00:00 2001 From: Yogeshwar Srikrishnan Date: Wed, 8 Jun 2011 18:29:32 -0500 Subject: Changing to legacy auth to standard wsgi middleware. --- bin/keystone | 18 ++-- bin/keystone-auth | 2 +- etc/keystone.conf | 20 +++- keystone/frontends/rackspace_legacy_auth.py | 149 ++++++++++------------------ keystone/logic/service.py | 5 +- keystone/server.py | 94 +----------------- test/unit/test_common.py | 2 +- 7 files changed, 87 insertions(+), 203 deletions(-) mode change 100644 => 100755 test/unit/test_common.py diff --git a/bin/keystone b/bin/keystone index 04e1659a..ef4dfefc 100755 --- a/bin/keystone +++ b/bin/keystone @@ -50,7 +50,12 @@ if __name__ == '__main__': common_group.add_option('-a', '--admin-port', default=8081, dest="admin_port", metavar="PORT", help = "specifies port for Admin API to listen" - "on (default is 8080)") + "on (default is 8081)") + + common_group.add_option('-r', '--rackspace-legacy-port', default=8082, + dest="rackspace_legacy_port", metavar="PORT", + help = "specifies port for Rackspace Legacy API to listen" + "on (default is 8082)") # Parse arguments and load config (options, args) = config.parse_options(parser) @@ -58,7 +63,7 @@ if __name__ == '__main__': # Start services try: # Load Service API server - conf, app = config.load_paste_app('server', options, args) + conf, app = config.load_paste_app('keystone-legacy-auth', options, args) debug = options.get('debug') or conf.get('debug', False) debug = debug in [True, "True", "1"] @@ -69,21 +74,20 @@ if __name__ == '__main__': print "Using config file:", config_file server = wsgi.Server() - server.start(app, int(conf['bind_port']), conf['bind_host']) - print "Service API listening on %s:%s" % (conf['bind_host'], - conf['bind_port']) + server.start(app, int(conf['server_bind_port']), conf['server_bind_host']) + print "Service API listening on %s:%s" % (conf['server_bind_host'], + conf['server_bind_port']) # Load Admin API server admin_conf, admin_app = config.load_paste_app('admin', options, args) admin_server = wsgi.Server() admin_bind = options.get('admin_port') or admin_conf.get('bind_port') - if conf['bind_port'] == admin_bind: + if conf['server_bind_host'] == admin_bind: admin_bind += 1 admin_server.start(admin_app, int(admin_bind), admin_conf['bind_host']) print "Admin API listening on %s:%s" % (admin_conf['bind_host'], admin_bind) - # Wait until done server.wait() except RuntimeError, e: diff --git a/bin/keystone-auth b/bin/keystone-auth index c83af24c..ea81c769 100755 --- a/bin/keystone-auth +++ b/bin/keystone-auth @@ -62,7 +62,7 @@ if __name__ == '__main__': # Load Service API server conf, app = config.load_paste_app('server', options, args) server = wsgi.Server() - server.start(app, int(conf['bind_port']), conf['bind_host']) + server.start(app, int(conf['server_bind_port']), conf['server_bind_host']) print "Service API listening on %s:%s" % (conf['bind_host'], conf['bind_port']) server.wait() diff --git a/etc/keystone.conf b/etc/keystone.conf index e9c59046..bcc33a09 100644 --- a/etc/keystone.conf +++ b/etc/keystone.conf @@ -26,6 +26,15 @@ sql_connection = sqlite:///../keystone/keystone.db # sql_idle_timeout = 30 +#Dictionary Maps every service to a header.Missing services would get header X_(SERVICE_NAME) Key => Service Name, Value => Header Name +service-header-mappings = {'cloudServers' : 'X-Server-Management-Url' , 'cloudFiles' : 'X-Storage-Url', 'cloudFilesCDN' : 'X-CDN-Management-Url'} + +# Address to bind the API server +#TODO Properties defined within app not available via pipeline.Till then server props stay outside. +server_bind_host = 0.0.0.0 + +# Port the bind the API server to +server_bind_port = 8080 [app:admin] paste.app_factory = keystone.server:admin_app_factory @@ -39,8 +48,11 @@ bind_port = 8081 [app:server] paste.app_factory = keystone.server:app_factory -# Address to bind the API server -bind_host = 0.0.0.0 +[pipeline:keystone-legacy-auth] +pipeline = + rackspace_legacy_auth + server + +[filter:rackspace_legacy_auth] +paste.filter_factory = keystone.frontends.legacy_auth_frontend:filter_factory -# Port the bind the API server to -bind_port = 8080 diff --git a/keystone/frontends/rackspace_legacy_auth.py b/keystone/frontends/rackspace_legacy_auth.py index 359aaf13..75c86b52 100755 --- a/keystone/frontends/rackspace_legacy_auth.py +++ b/keystone/frontends/rackspace_legacy_auth.py @@ -16,25 +16,24 @@ # See the License for the specific language governing permissions and # limitations under the License. # Not Yet PEP8 standardized - - """ RACKSPACE LEGACY AUTH - STUB -This WSGI component -- collects, transforms and forwards identity information from the keystone authentication process - into rackspace specific format. +This WSGI component +- transforms rackspace auth header credentials to keystone credentials +and makes an authentication call on keystone.- transforms response it +receives into custom headers defined in properties and returns +the response. """ import os import sys -import routes import eventlet import optparse -import httplib2 +import httplib import json import ast -from webob import Response +from webob.exc import Request, Response from paste.deploy import loadapp from webob.exc import HTTPUnauthorized, HTTPInternalServerError @@ -50,55 +49,57 @@ import keystone.utils as utils from keystone.common import wsgi from keystone.common import config -class RackspaceLegacyAuthController(wsgi.Controller): - """ - Auth Controller for v1.x - - Controller for token related operations - """ - - def __init__(self, options): - self.options = options - self.request = None - # where to find the auth service (we use this to validate tokens) - self.auth_host = options.get('auth_host') - self.auth_port = int(options.get('auth_port')) - self.auth_protocol = options.get('auth_protocol', 'https') - self.auth_location = "%s://%s:%s" % (self.auth_protocol, - self.auth_host, - self.auth_port) - - @utils.wrap_error - def authenticate(self, req): - header = httplib2.Http(".cache") - self.request = req - - url = '%s/v2.0/tokens' % self.auth_location - - body = {"passwordCredentials": {"username": utils.get_auth_user(self.request), - "password": utils.get_auth_key(self.request)}} +PROTOCOL_NAME = "Legacy Authentication" - resp, content = header.request(url, "POST", body=json.dumps(body), - headers={"Content-Type": "application/json"}) +class AuthProtocol(object): - if int(resp['status']) != 200: - response = Response() - response.status = resp.status - response.reason = resp.reason - return response + """Legacy Auth Middleware that handles authenticating client calls""" + + def __init__(self, app, conf): + """ Common initialization code """ + print "Starting the %s component" % PROTOCOL_NAME + self.conf = conf + self.app = app + + + def __call__(self, env, start_response): + """ Handle incoming request. Transform. And send downstream. """ + self.start_response = start_response + self.env = env + self.request = Request(env) + if self.request.path.startswith('/v1.0') or self.request.path.startswith('/v1.1'): + #Handle 1.0 and 1.1 calls via wrapper. + params = {"passwordCredentials": {"username": utils.get_auth_user(self.request), + "password": utils.get_auth_key(self.request)}} + + new_request = Request.blank('/v2.0/tokens') + new_request.headers['Content-type'] = 'application/json' + new_request.accept = 'text/json' + new_request.body = json.dumps(params) + new_request.method = 'POST' + response = new_request.get_response(self.app) - content = json.loads(content) - + #Handle failures. + if not str(response.status).startswith('20'): + return response(env, start_response) + + headers = self.transform_keystone_auth_to_legacy_headers(json.loads(response.body)) + resp = utils.send_legacy_result(204, headers) + return resp(env, start_response) + else: + # Other calls pass to downstream WSGI component + return self.app(self.env, self.start_response) + + def transform_keystone_auth_to_legacy_headers(self, content): headers = {} - if "auth" in content: auth = content["auth"] - if "token" in auth: headers["X-Auth-Token"] = auth["token"]["id"] - if "serviceCatalog" in auth: services = auth["serviceCatalog"] - service_mappings = ast.literal_eval(self.options["service-header-mappings"]) + service_mappings = ast.literal_eval( + self.conf["service-header-mappings"]) for service in services: service_name = service service_urls = '' @@ -108,53 +109,11 @@ class RackspaceLegacyAuthController(wsgi.Controller): service_urls += endpoint["publicURL"] if len(service_urls) > 0: if service_mappings.get(service_name): - headers[service_mappings.get(service_name)] = service_urls + headers[service_mappings.get( + service_name)] = service_urls else: - #For Services that are not mapped user X- prefix followed by service name. + #For Services that are not mapped, + #use X- prefix followed by service name. headers['X-' + service_name.upper()] = service_urls - return utils.send_legacy_result(204, headers) - -class RackspaceLegacyAuthenticator(wsgi.Router): - """Rackspace Legacy Protocol that handles authenticating client calls made in Rackspace format.""" - - def __init__(self, options): - self.options = options - mapper = routes.Mapper() - # Legacy Token Operations - legacy_auth_controller = RackspaceLegacyAuthController(options) - mapper.connect("/v1.0", controller=legacy_auth_controller, - action="authenticate") - mapper.connect("/v1.0/", controller=legacy_auth_controller, - action="authenticate") - mapper.connect("/v1.1/tokens", controller=legacy_auth_controller, - action="authenticate", - conditions=dict(method=["POST"])) - mapper.connect("/v1.1/tokens/", controller=legacy_auth_controller, - action="authenticate", - conditions=dict(method=["POST"])) - super(RackspaceLegacyAuthenticator, self).__init__(mapper) - -def app_factory(global_conf, ** local_conf): - conf = global_conf.copy() - conf.update(local_conf) - return RackspaceLegacyAuthenticator(conf) - -if __name__ == "__main__": - expected_options = {'verbose': False, 'debug': False, - 'config_file': 'rackspace_legacy_auth.conf'} - - parser = optparse.OptionParser(version='%%prog %s' % keystone.version) - # Parse arguments and load config - (options, args) = config.parse_options(parser) - # Start services - try: - conf, app = config.load_paste_app('rackspace_legacy_auth', expected_options, args) - server = wsgi.Server() - server.start(app, int(conf['bind_port']), conf['bind_host']) - print "Rackspace Legacy Service API listening on %s:%s" % (conf['bind_host'], - conf['bind_port']) - server.wait() - - except RuntimeError, e: - sys.exit("ERROR: %s" % e) - + return headers + diff --git a/keystone/logic/service.py b/keystone/logic/service.py index 69875b00..4de20832 100755 --- a/keystone/logic/service.py +++ b/keystone/logic/service.py @@ -76,10 +76,11 @@ class IdentityService(object): dtoken.token_id = str(uuid.uuid4()) dtoken.user_id = duser.id if credentials.tenant_id: - dtoken.tenant_id = credentials.tenant_id + dtoken.tenant_id = credentials.tenant_id dtoken.expires = datetime.now() + timedelta(days=1) db_api.token_create(dtoken) - #if tenant_id is passed in the call that tenant_id is passed else user's default tenant_id is used. + #if tenant_id is passed in the call that tenant_id is passed else + #user's default tenant_id is used. return self.__get_auth_data(dtoken, tenant_id) def validate_token(self, admin_token, token_id, belongs_to=None): diff --git a/keystone/server.py b/keystone/server.py index b306a195..8dff1159 100755 --- a/keystone/server.py +++ b/keystone/server.py @@ -175,70 +175,6 @@ class AuthController(wsgi.Controller): service.revoke_token(utils.get_auth_token(req), token_id)) -class LegacyAuthController(wsgi.Controller): - """ - Auth Controller for v1.x - - Controller for token related operations - """ - - def __init__(self, options): - self.options = options - self.request = None - - @utils.wrap_error - def authenticate(self, req): - self.request = req - - creds = auth.PasswordCredentials(utils.get_auth_user(req), - utils.get_auth_key(req), - None) - - """HTTP/1.1 204 No Content - Date: Mon, 12 Nov 2007 15:32:21 GMT - X-Storage-Url: https://storage.clouddrive.com/v1/CF_xer7_34 - X-CDN-Management-Url: https://cdn.clouddrive.com/v1/CF_xer7_34 - X-Auth-Token: eaaafd18-0fed-4b3a-81b4-663c99ec1cbb - Content-Length: 0 - Content-Type: text/plain; charset=UTF-8""" - - result = service.authenticate(creds) - headers = {"X-Auth-Token": result.token.token_id} - server_urls = '' - files_urls = '' - files_cdn_urls = '' - if result.base_urls != None: - for base_url in result.base_urls: - if base_url.service == 'cloudServers': - if base_url.public_url: - if(len(server_urls) > 0): - server_urls += ',' - server_urls += base_url.public_url.replace('%tenant_id%', result.token.tenant_id) - - if base_url.service == 'cloudFiles': - if base_url.public_url: - if(len(files_urls) > 0): - files_urls += ',' - files_urls += base_url.public_url.replace('%tenant_id%', result.token.tenant_id) - - if base_url.service == 'cloudFilesCDN': - if base_url.public_url: - if(len(files_cdn_urls) > 0): - files_cdn_urls += ',' - files_cdn_urls += base_url.public_url.replace('%tenant_id%', result.token.tenant_id) - - - if len(server_urls) > 0: - headers["X-Server-Management-Url"] = server_urls - - if len(files_urls) > 0: - headers["X-Storage-Url"] = files_urls - - if len(files_cdn_urls) > 0: - headers["X-CDN-Management-Url"] = files_cdn_urls - - return utils.send_legacy_result(204, headers) - - class TenantController(wsgi.Controller): """ Tenant Controller - @@ -596,22 +532,8 @@ class KeystoneAPI(wsgi.Router): db_api.configure_db(options) - # Legacy Token Operations - auth_controller = AuthController(options) - legacy_auth_controller = LegacyAuthController(options) - mapper.connect("/v1.0", controller=legacy_auth_controller, - action="authenticate") - mapper.connect("/v1.0/", controller=legacy_auth_controller, - action="authenticate") - - mapper.connect("/v1.1/tokens", controller=auth_controller, - action="authenticate", - conditions=dict(method=["POST"])) - mapper.connect("/v1.1/tokens/", controller=auth_controller, - action="authenticate", - conditions=dict(method=["POST"])) - # Token Operations + auth_controller = AuthController(options) mapper.connect("/v2.0/tokens", controller=auth_controller, action="authenticate", conditions=dict(method=["POST"])) @@ -660,20 +582,6 @@ class KeystoneAdminAPI(wsgi.Router): mapper = routes.Mapper() db_api.configure_db(options) - - # Legacy Token Operations - legacy_auth_controller = LegacyAuthController(options) - mapper.connect("/v1.0", controller=legacy_auth_controller, - action="authenticate") - mapper.connect("/v1.0/", controller=legacy_auth_controller, - action="authenticate") - mapper.connect("/v1.1/tokens", controller=legacy_auth_controller, - action="authenticate", - conditions=dict(method=["POST"])) - mapper.connect("/v1.1/tokens/", controller=legacy_auth_controller, - action="authenticate", - conditions=dict(method=["POST"])) - # Token Operations auth_controller = AuthController(options) mapper.connect("/v2.0/tokens", controller=auth_controller, diff --git a/test/unit/test_common.py b/test/unit/test_common.py old mode 100644 new mode 100755 index e77f7fc8..be017285 --- a/test/unit/test_common.py +++ b/test/unit/test_common.py @@ -25,7 +25,7 @@ sys.path.append(os.path.abspath(os.path.join(os.path.abspath(__file__), import unittest URL = 'http://localhost:8081/v2.0/' -URLv1 = 'http://localhost:8081/v1.0/' +URLv1 = 'http://localhost:8080/v1.0/' def get_token(user, pswd, tenant_id, kind=''): header = httplib2.Http(".cache") -- cgit From d02151d7cf2ec3a62f45eb869960d429b1f6298d Mon Sep 17 00:00:00 2001 From: Yogeshwar Srikrishnan Date: Wed, 8 Jun 2011 23:23:08 -0500 Subject: Changing to legacy auth to standard wsgi middleware.Name change of some of the files. --- keystone/frontends/legacy_auth_frontend.py | 140 +++++++++++++++++++++++++++++ 1 file changed, 140 insertions(+) create mode 100644 keystone/frontends/legacy_auth_frontend.py diff --git a/keystone/frontends/legacy_auth_frontend.py b/keystone/frontends/legacy_auth_frontend.py new file mode 100644 index 00000000..5e86d654 --- /dev/null +++ b/keystone/frontends/legacy_auth_frontend.py @@ -0,0 +1,140 @@ +#!/usr/bin/env python +# vim: tabstop=4 shiftwidth=4 softtabstop=4 +# +# Copyright (c) 2010-2011 OpenStack, LLC. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# Not Yet PEP8 standardized +""" +RACKSPACE LEGACY AUTH - STUB + +This WSGI component +- transforms rackspace auth header credentials to keystone credentials +and makes an authentication call on keystone.- transforms response it +receives into custom headers defined in properties and returns +the response. +""" +import os +import sys +import eventlet +import optparse +import httplib +import json +import ast + +from webob.exc import Request, Response +from paste.deploy import loadapp +from webob.exc import HTTPUnauthorized, HTTPInternalServerError + +POSSIBLE_TOPDIR = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]), + os.pardir, + os.pardir, + os.pardir)) +if os.path.exists(os.path.join(POSSIBLE_TOPDIR, 'keystone', '__init__.py')): + sys.path.insert(0, POSSIBLE_TOPDIR) + +import keystone +import keystone.utils as utils +from keystone.common import wsgi +from keystone.common import config + +PROTOCOL_NAME = "Legacy Authentication" + +class AuthProtocol(object): + + """Legacy Auth Middleware that handles authenticating client calls""" + + def __init__(self, app, conf): + """ Common initialization code """ + print "Starting the %s component" % PROTOCOL_NAME + self.conf = conf + self.app = app + + + def __call__(self, env, start_response): + """ Handle incoming request. Transform. And send downstream. """ + self.start_response = start_response + self.env = env + self.request = Request(env) + if self.request.path.startswith('/v1.0') or self.request.path.startswith('/v1.1'): + #Handle 1.0 and 1.1 calls via wrapper. + params = {"passwordCredentials": {"username": utils.get_auth_user(self.request), + "password": utils.get_auth_key(self.request)}} + + new_request = Request.blank('/v2.0/tokens') + new_request.headers['Content-type'] = 'application/json' + new_request.accept = 'text/json' + new_request.body = json.dumps(params) + new_request.method = 'POST' + response = new_request.get_response(self.app) + + #Handle failures. + if not str(response.status).startswith('20'): + return response(env, start_response) + + headers = self.transform_keystone_auth_to_legacy_headers(json.loads(response.body)) + resp = utils.send_legacy_result(204, headers) + return resp(env, start_response) + else: + # Other calls pass to downstream WSGI component + return self.app(self.env, self.start_response) + + def get_auth_user(self): + auth_user = None + if "X-Auth-User" in self.request.headers: + auth_user = self.request.headers["X-Auth-User"] + return auth_user + + def get_auth_key(self): + auth_key = None + if "X-Auth-Key" in self.request.headers: + auth_key = self.request.headers["X-Auth-Key"] + return auth_key + + + def transform_keystone_auth_to_legacy_headers(self, content): + headers = {} + if "auth" in content: + auth = content["auth"] + if "token" in auth: + headers["X-Auth-Token"] = auth["token"]["id"] + if "serviceCatalog" in auth: + services = auth["serviceCatalog"] + service_mappings = ast.literal_eval( + self.conf["service-header-mappings"]) + for service in services: + service_name = service + service_urls = '' + for endpoint in services[service_name]: + if len(service_urls) > 0: + service_urls += ',' + service_urls += endpoint["publicURL"] + if len(service_urls) > 0: + if service_mappings.get(service_name): + headers[service_mappings.get( + service_name)] = service_urls + else: + #For Services that are not mapped, + #use X- prefix followed by service name. + headers['X-' + service_name.upper()] = service_urls + return headers + +def filter_factory(global_conf, **local_conf): + """Returns a WSGI filter app for use with paste.deploy.""" + conf = global_conf.copy() + conf.update(local_conf) + + def auth_filter(app): + return AuthProtocol(app, conf) + return auth_filter -- cgit From ce24b59f91370e1eae2729bacd13a99a3fd343d7 Mon Sep 17 00:00:00 2001 From: Yogeshwar Srikrishnan Date: Wed, 8 Jun 2011 23:33:49 -0500 Subject: Removing redundant files. --- bin/rackspace-keystone | 104 ------------------------ etc/rackspace_legacy_auth.conf | 17 ---- keystone/frontends/rackspace_legacy_auth.py | 119 ---------------------------- 3 files changed, 240 deletions(-) delete mode 100755 bin/rackspace-keystone delete mode 100644 etc/rackspace_legacy_auth.conf delete mode 100755 keystone/frontends/rackspace_legacy_auth.py diff --git a/bin/rackspace-keystone b/bin/rackspace-keystone deleted file mode 100755 index 7dd20697..00000000 --- a/bin/rackspace-keystone +++ /dev/null @@ -1,104 +0,0 @@ -#!/usr/bin/env python -# vim: tabstop=4 shiftwidth=4 softtabstop=4 - -# Copyright 2010 United States Government as represented by the -# Administrator of the National Aeronautics and Space Administration. -# Copyright 2011 OpenStack LLC. -# All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Keystone Identity Server - Admin and Service API -""" - -import optparse -import os -import sys - -# If ../../keystone/__init__.py exists, add ../ to Python search path, so that -# it will override what happens to be installed in /usr/(local/)lib/python... -possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]), - os.pardir, - os.pardir)) -if os.path.exists(os.path.join(possible_topdir, 'keystone', '__init__.py')): - sys.path.insert(0, possible_topdir) - -import tools.tracer #load this first -import keystone -from keystone.common import config -from keystone.common import wsgi - - -if __name__ == '__main__': - # Initialize a parser for our configuration paramaters - parser = optparse.OptionParser(version='%%prog %s' % keystone.version) - common_group = config.add_common_options(parser) - config.add_log_options(parser) - - # Handle a special argument to support starting two endpoints - common_group.add_option('-a', '--admin-port', default=8081, - dest="admin_port", metavar="PORT", - help = "specifies port for Admin API to listen" - "on (default is 8081)") - - common_group.add_option('-r', '--rackspace-legacy-port', default=8082, - dest="rackspace_legacy_port", metavar="PORT", - help = "specifies port for Rackspace Legacy API to listen" - "on (default is 8082)") - - # Parse arguments and load config - (options, args) = config.parse_options(parser) - - # Start services - try: - # Load Service API server - conf, app = config.load_paste_app('server', options, args) - - debug = options.get('debug') or conf.get('debug', False) - debug = debug in [True, "True", "1"] - verbose = options.get('verbose') or conf.get('verbose', False) - verbose = verbose in [True, "True", "1"] - if debug or verbose: - config_file = config.find_config_file(options, args) - print "Using config file:", config_file - - server = wsgi.Server() - server.start(app, int(conf['bind_port']), conf['bind_host']) - print "Service API listening on %s:%s" % (conf['bind_host'], - conf['bind_port']) - - # Load Admin API server - admin_conf, admin_app = config.load_paste_app('admin', options, args) - admin_server = wsgi.Server() - admin_bind = options.get('admin_port') or admin_conf.get('bind_port') - if conf['bind_port'] == admin_bind: - admin_bind += 1 - admin_server.start(admin_app, int(admin_bind), - admin_conf['bind_host']) - print "Admin API listening on %s:%s" % (admin_conf['bind_host'], - admin_bind) - - #Load Rackspace Legacy API - options['config_file'] = 'rackspace_legacy_auth.conf' - print options.get('config_file') - conf, app = config.load_paste_app('rackspace_legacy_auth', options, args) - server = wsgi.Server() - server.start(app, int(conf['bind_port']), conf['bind_host']) - print "Rackspace Legacy Service API listening on %s:%s" % (conf['bind_host'], - conf['bind_port']) - - # Wait until done - server.wait() - except RuntimeError, e: - sys.exit("ERROR: %s" % e) diff --git a/etc/rackspace_legacy_auth.conf b/etc/rackspace_legacy_auth.conf deleted file mode 100644 index e8a8cbd8..00000000 --- a/etc/rackspace_legacy_auth.conf +++ /dev/null @@ -1,17 +0,0 @@ -[DEFAULT] - -[app:rackspace_legacy_auth] -paste.app_factory = keystone.frontends.rackspace_legacy_auth:app_factory - -# Keystone Service Details -auth_host = 127.0.0.1 -auth_port = 8081 -auth_protocol = http - -# Address to bind the API server -bind_host = 0.0.0.0 - -# Port the bind the API server to -bind_port = 8082 - -service-header-mappings = {'cloudServers' : 'X-Server-Management-Url' , 'cloudFiles' : 'X-Storage-Url', 'cloudFilesCDN' : 'X-CDN-Management-Url'} \ No newline at end of file diff --git a/keystone/frontends/rackspace_legacy_auth.py b/keystone/frontends/rackspace_legacy_auth.py deleted file mode 100755 index 75c86b52..00000000 --- a/keystone/frontends/rackspace_legacy_auth.py +++ /dev/null @@ -1,119 +0,0 @@ -#!/usr/bin/env python -# vim: tabstop=4 shiftwidth=4 softtabstop=4 -# -# Copyright (c) 2010-2011 OpenStack, LLC. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# Not Yet PEP8 standardized -""" -RACKSPACE LEGACY AUTH - STUB - -This WSGI component -- transforms rackspace auth header credentials to keystone credentials -and makes an authentication call on keystone.- transforms response it -receives into custom headers defined in properties and returns -the response. -""" -import os -import sys -import eventlet -import optparse -import httplib -import json -import ast - -from webob.exc import Request, Response -from paste.deploy import loadapp -from webob.exc import HTTPUnauthorized, HTTPInternalServerError - -POSSIBLE_TOPDIR = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]), - os.pardir, - os.pardir, - os.pardir)) -if os.path.exists(os.path.join(POSSIBLE_TOPDIR, 'keystone', '__init__.py')): - sys.path.insert(0, POSSIBLE_TOPDIR) - -import keystone -import keystone.utils as utils -from keystone.common import wsgi -from keystone.common import config - -PROTOCOL_NAME = "Legacy Authentication" - -class AuthProtocol(object): - - """Legacy Auth Middleware that handles authenticating client calls""" - - def __init__(self, app, conf): - """ Common initialization code """ - print "Starting the %s component" % PROTOCOL_NAME - self.conf = conf - self.app = app - - - def __call__(self, env, start_response): - """ Handle incoming request. Transform. And send downstream. """ - self.start_response = start_response - self.env = env - self.request = Request(env) - if self.request.path.startswith('/v1.0') or self.request.path.startswith('/v1.1'): - #Handle 1.0 and 1.1 calls via wrapper. - params = {"passwordCredentials": {"username": utils.get_auth_user(self.request), - "password": utils.get_auth_key(self.request)}} - - new_request = Request.blank('/v2.0/tokens') - new_request.headers['Content-type'] = 'application/json' - new_request.accept = 'text/json' - new_request.body = json.dumps(params) - new_request.method = 'POST' - response = new_request.get_response(self.app) - - #Handle failures. - if not str(response.status).startswith('20'): - return response(env, start_response) - - headers = self.transform_keystone_auth_to_legacy_headers(json.loads(response.body)) - resp = utils.send_legacy_result(204, headers) - return resp(env, start_response) - else: - # Other calls pass to downstream WSGI component - return self.app(self.env, self.start_response) - - def transform_keystone_auth_to_legacy_headers(self, content): - headers = {} - if "auth" in content: - auth = content["auth"] - if "token" in auth: - headers["X-Auth-Token"] = auth["token"]["id"] - if "serviceCatalog" in auth: - services = auth["serviceCatalog"] - service_mappings = ast.literal_eval( - self.conf["service-header-mappings"]) - for service in services: - service_name = service - service_urls = '' - for endpoint in services[service_name]: - if len(service_urls) > 0: - service_urls += ',' - service_urls += endpoint["publicURL"] - if len(service_urls) > 0: - if service_mappings.get(service_name): - headers[service_mappings.get( - service_name)] = service_urls - else: - #For Services that are not mapped, - #use X- prefix followed by service name. - headers['X-' + service_name.upper()] = service_urls - return headers - -- cgit From 38c2f72090e71e2376996fb3f5cf8b30aa59508f Mon Sep 17 00:00:00 2001 From: Yogeshwar Srikrishnan Date: Thu, 9 Jun 2011 00:16:58 -0500 Subject: PEP8 changes. --- bin/keystone | 14 ++++++++------ bin/keystone-auth | 7 ++++--- keystone/common/config.py | 12 +++++------- keystone/db/sqlalchemy/api.py | 8 ++++---- keystone/frontends/legacy_auth_frontend.py | 27 +++++++++++++-------------- keystone/logic/types/auth.py | 29 ++++++++++++++++++----------- test/unit/test_authentication.py | 15 +++++++-------- 7 files changed, 59 insertions(+), 53 deletions(-) mode change 100644 => 100755 keystone/frontends/legacy_auth_frontend.py diff --git a/bin/keystone b/bin/keystone index ef4dfefc..f120bbed 100755 --- a/bin/keystone +++ b/bin/keystone @@ -33,8 +33,8 @@ possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]), os.pardir)) if os.path.exists(os.path.join(possible_topdir, 'keystone', '__init__.py')): sys.path.insert(0, possible_topdir) - -import tools.tracer #load this first +#load this first +import tools.tracer import keystone from keystone.common import config from keystone.common import wsgi @@ -49,12 +49,12 @@ if __name__ == '__main__': # Handle a special argument to support starting two endpoints common_group.add_option('-a', '--admin-port', default=8081, dest="admin_port", metavar="PORT", - help = "specifies port for Admin API to listen" + help="specifies port for Admin API to listen" "on (default is 8081)") common_group.add_option('-r', '--rackspace-legacy-port', default=8082, dest="rackspace_legacy_port", metavar="PORT", - help = "specifies port for Rackspace Legacy API to listen" + help="specifies port for Rackspace Legacy API to listen" "on (default is 8082)") # Parse arguments and load config @@ -63,7 +63,8 @@ if __name__ == '__main__': # Start services try: # Load Service API server - conf, app = config.load_paste_app('keystone-legacy-auth', options, args) + conf, app = config.load_paste_app( + 'keystone-legacy-auth', options, args) debug = options.get('debug') or conf.get('debug', False) debug = debug in [True, "True", "1"] @@ -74,7 +75,8 @@ if __name__ == '__main__': print "Using config file:", config_file server = wsgi.Server() - server.start(app, int(conf['server_bind_port']), conf['server_bind_host']) + server.start(app, int(conf['server_bind_port']), + conf['server_bind_host']) print "Service API listening on %s:%s" % (conf['server_bind_host'], conf['server_bind_port']) diff --git a/bin/keystone-auth b/bin/keystone-auth index ea81c769..6159d3ab 100755 --- a/bin/keystone-auth +++ b/bin/keystone-auth @@ -33,8 +33,8 @@ possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]), os.pardir)) if os.path.exists(os.path.join(possible_topdir, 'keystone', '__init__.py')): sys.path.insert(0, possible_topdir) - -import tools.tracer #load this first +#load this first +import tools.tracer import keystone from keystone.common import config from keystone.common import wsgi @@ -62,7 +62,8 @@ if __name__ == '__main__': # Load Service API server conf, app = config.load_paste_app('server', options, args) server = wsgi.Server() - server.start(app, int(conf['server_bind_port']), conf['server_bind_host']) + server.start(app, int(conf['server_bind_port']), + conf['server_bind_host']) print "Service API listening on %s:%s" % (conf['bind_host'], conf['bind_port']) server.wait() diff --git a/keystone/common/config.py b/keystone/common/config.py index ed8cb228..34281192 100755 --- a/keystone/common/config.py +++ b/keystone/common/config.py @@ -227,7 +227,7 @@ def find_config_file(options, args): We search for the paste config file in the following order: * If --config-file option is used, use that * If args[0] is a file, use that - * Search for config file in standard directories: + * Search for keystone.conf in standard directories: * . * ~.keystone/ * ~ @@ -242,16 +242,14 @@ def find_config_file(options, args): os.pardir, os.pardir)) fix_path = lambda p: os.path.abspath(os.path.expanduser(p)) - file_name = 'keystone.conf' if options.get('config_file'): - file_name = options.get('config_file') if os.path.exists(options['config_file']): return fix_path(options['config_file']) elif args: if os.path.exists(args[0]): return fix_path(args[0]) - # Handle standard directory search for keystone.conf or passed conf file. + # Handle standard directory search for keystone.conf config_file_dirs = [fix_path(os.getcwd()), fix_path(os.path.join('~', '.keystone')), fix_path('~'), @@ -259,15 +257,15 @@ def find_config_file(options, args): '/etc'] for cfg_dir in config_file_dirs: - cfg_file = os.path.join(cfg_dir, file_name) + cfg_file = os.path.join(cfg_dir, 'keystone.conf') if os.path.exists(cfg_file): return cfg_file else: if os.path.exists(os.path.join(POSSIBLE_TOPDIR, 'etc', \ - file_name)): + 'keystone.conf')): # For debug only config_file = os.path.join(POSSIBLE_TOPDIR, 'etc', \ - file_name) + 'keystone.conf') return config_file diff --git a/keystone/db/sqlalchemy/api.py b/keystone/db/sqlalchemy/api.py index 70094f4b..df1d4d4e 100755 --- a/keystone/db/sqlalchemy/api.py +++ b/keystone/db/sqlalchemy/api.py @@ -1213,12 +1213,12 @@ def baseurls_ref_delete(id, session=None): baseurls_ref = baseurls_ref_get(id, session) session.delete(baseurls_ref) + def tenant_baseurls_get_all(tenant_id, session=None): if not session: session = get_session() tba = aliased(models.TenantBaseURLAssociation) baseUrls = aliased(models.BaseUrls) - return session.query(baseUrls).join((tba, tba.baseURLs_id == baseUrls.id)).\ - filter(tba.tenant_id == tenant_id).all() - - + return session.query(baseUrls).join((tba, + tba.baseURLs_id == baseUrls.id)).\ + filter(tba.tenant_id == tenant_id).all() diff --git a/keystone/frontends/legacy_auth_frontend.py b/keystone/frontends/legacy_auth_frontend.py old mode 100644 new mode 100755 index 5e86d654..9ca4e84e --- a/keystone/frontends/legacy_auth_frontend.py +++ b/keystone/frontends/legacy_auth_frontend.py @@ -27,7 +27,6 @@ the response. """ import os import sys -import eventlet import optparse import httplib import json @@ -51,8 +50,8 @@ from keystone.common import config PROTOCOL_NAME = "Legacy Authentication" + class AuthProtocol(object): - """Legacy Auth Middleware that handles authenticating client calls""" def __init__(self, app, conf): @@ -61,16 +60,17 @@ class AuthProtocol(object): self.conf = conf self.app = app - def __call__(self, env, start_response): """ Handle incoming request. Transform. And send downstream. """ self.start_response = start_response self.env = env self.request = Request(env) - if self.request.path.startswith('/v1.0') or self.request.path.startswith('/v1.1'): + if self.request.path.startswith('/v1.0' + ) or self.request.path.startswith('/v1.1'): #Handle 1.0 and 1.1 calls via wrapper. - params = {"passwordCredentials": {"username": utils.get_auth_user(self.request), - "password": utils.get_auth_key(self.request)}} + params = {"passwordCredentials": + {"username": utils.get_auth_user(self.request), + "password": utils.get_auth_key(self.request)}} new_request = Request.blank('/v2.0/tokens') new_request.headers['Content-type'] = 'application/json' @@ -78,12 +78,11 @@ class AuthProtocol(object): new_request.body = json.dumps(params) new_request.method = 'POST' response = new_request.get_response(self.app) - #Handle failures. if not str(response.status).startswith('20'): - return response(env, start_response) - - headers = self.transform_keystone_auth_to_legacy_headers(json.loads(response.body)) + return response(env, start_response) + headers = self.transform_keystone_auth_to_legacy_headers( + json.loads(response.body)) resp = utils.send_legacy_result(204, headers) return resp(env, start_response) else: @@ -101,8 +100,7 @@ class AuthProtocol(object): if "X-Auth-Key" in self.request.headers: auth_key = self.request.headers["X-Auth-Key"] return auth_key - - + def transform_keystone_auth_to_legacy_headers(self, content): headers = {} if "auth" in content: @@ -129,7 +127,8 @@ class AuthProtocol(object): #use X- prefix followed by service name. headers['X-' + service_name.upper()] = service_urls return headers - + + def filter_factory(global_conf, **local_conf): """Returns a WSGI filter app for use with paste.deploy.""" conf = global_conf.copy() @@ -137,4 +136,4 @@ def filter_factory(global_conf, **local_conf): def auth_filter(app): return AuthProtocol(app, conf) - return auth_filter + return auth_filter diff --git a/keystone/logic/types/auth.py b/keystone/logic/types/auth.py index 804a8841..4b90b8ca 100755 --- a/keystone/logic/types/auth.py +++ b/keystone/logic/types/auth.py @@ -120,7 +120,7 @@ class User(object): class AuthData(object): "Authentation Information returned upon successful login." - def __init__(self, token, base_urls = None): + def __init__(self, token, base_urls=None): self.token = token self.base_urls = base_urls self.d = {} @@ -129,7 +129,7 @@ class AuthData(object): def to_xml(self): dom = etree.Element("auth", - xmlns="http://docs.openstack.org/identity/api/v2.0") + xmlns="http://docs.openstack.org/identity/api/v2.0") token = etree.Element("token", expires=self.token.expires.isoformat()) token.set("id", self.token.token_id) @@ -138,22 +138,26 @@ class AuthData(object): service_catalog = etree.Element("serviceCatalog") for key, key_base_urls in self.d.items(): service = etree.Element("service", - name = key) + name=key) for base_url in key_base_urls: endpoint = etree.Element("endpoint") if base_url.region: endpoint.set("region", base_url.region) if base_url.public_url: - endpoint.set("publicURL", base_url.public_url.replace('%tenant_id%',self.token.tenant_id)) + endpoint.set("publicURL", base_url.public_url.replace( + '%tenant_id%', self.token.tenant_id)) if base_url.admin_url: - endpoint.set("adminURL", base_url.admin_url.replace('%tenant_id%',self.token.tenant_id)) + endpoint.set("adminURL", base_url.admin_url.replace( + '%tenant_id%', self.token.tenant_id)) if base_url.internal_url: - endpoint.set("internalURL", base_url.internal_url.replace('%tenant_id%',self.token.tenant_id)) + endpoint.set("internalURL", + base_url.internal_url.replace('%tenant_id%', + self.token.tenant_id)) service.append(endpoint) service_catalog.append(service) dom.append(service_catalog) return etree.tostring(dom) - + def __convert_baseurls_to_dict(self): for base_url in self.base_urls: if base_url.service not in self.d: @@ -173,13 +177,16 @@ class AuthData(object): for base_url in key_base_urls: endpoint = {} if base_url.region: - endpoint["region"] = base_url.region + endpoint["region"] = base_url.region if base_url.public_url: - endpoint["publicURL"] = base_url.public_url.replace('%tenant_id%',self.token.tenant_id) + endpoint["publicURL"] = base_url.public_url.replace( + '%tenant_id%', self.token.tenant_id) if base_url.admin_url: - endpoint["adminURL"] = base_url.admin_url.replace('%tenant_id%',self.token.tenant_id) + endpoint["adminURL"] = base_url.admin_url.replace( + '%tenant_id%', self.token.tenant_id) if base_url.internal_url: - endpoint["internalURL"] = base_url.internal_url.replace('%tenant_id%',self.token.tenant_id) + endpoint["internalURL"] = base_url.internal_url.replace + ('%tenant_id%', self.token.tenant_id) endpoints.append(endpoint) service_catalog[key] = endpoints auth["serviceCatalog"] = service_catalog diff --git a/test/unit/test_authentication.py b/test/unit/test_authentication.py index a1751c5e..74089023 100755 --- a/test/unit/test_authentication.py +++ b/test/unit/test_authentication.py @@ -38,11 +38,11 @@ class AuthenticationTest(unittest.TestCase): #self.user = utils.get_user() self.userdisabled = utils.get_userdisabled() self.auth_token = utils.get_auth_token() - utils.create_baseurls_ref(self.tenant,"1", + utils.create_baseurls_ref(self.tenant, "1", str(self.auth_token)) - utils.create_baseurls_ref(self.tenant,"2", - str(self.auth_token)) - utils.create_baseurls_ref(self.tenant,"3", + utils.create_baseurls_ref(self.tenant, "2", + str(self.auth_token)) + utils.create_baseurls_ref(self.tenant, "3", str(self.auth_token)) #self.exp_auth_token = utils.get_exp_auth_token() #self.disabled_token = utils.get_disabled_token() @@ -68,7 +68,6 @@ class AuthenticationTest(unittest.TestCase): self.tenant) self.assertEqual(200, int(resp['status'])) self.assertEqual('application/xml', utils.content_type(resp)) - #verify content dom = etree.Element("root") dom.append(etree.fromstring(content)) @@ -76,12 +75,12 @@ class AuthenticationTest(unittest.TestCase): "auth") if auth == None: self.fail("Expecting Auth") - service_catalog = auth.find("{http://docs.openstack.org/identity/api/v2.0}" \ - "serviceCatalog") + service_catalog = auth.find( + "{http://docs.openstack.org/identity/api/v2.0}" \ + "serviceCatalog") if service_catalog == None: self.fail("Expecting Service Catalog") - def test_a_authorize_legacy(self): resp, content = utils.get_token_legacy('joeuser', 'secrete') self.assertEqual(204, int(resp['status'])) -- cgit From 0e1602a6cdb46ea664688ddd48d77b460d820a68 Mon Sep 17 00:00:00 2001 From: Yogeshwar Srikrishnan Date: Thu, 9 Jun 2011 00:27:42 -0500 Subject: Code cleanup. --- bin/keystone | 5 ----- keystone/frontends/legacy_auth_frontend.py | 18 ++++-------------- keystone/logic/types/auth.py | 2 +- 3 files changed, 5 insertions(+), 20 deletions(-) diff --git a/bin/keystone b/bin/keystone index f120bbed..decdfc51 100755 --- a/bin/keystone +++ b/bin/keystone @@ -52,11 +52,6 @@ if __name__ == '__main__': help="specifies port for Admin API to listen" "on (default is 8081)") - common_group.add_option('-r', '--rackspace-legacy-port', default=8082, - dest="rackspace_legacy_port", metavar="PORT", - help="specifies port for Rackspace Legacy API to listen" - "on (default is 8082)") - # Parse arguments and load config (options, args) = config.parse_options(parser) diff --git a/keystone/frontends/legacy_auth_frontend.py b/keystone/frontends/legacy_auth_frontend.py index 9ca4e84e..dcd03477 100755 --- a/keystone/frontends/legacy_auth_frontend.py +++ b/keystone/frontends/legacy_auth_frontend.py @@ -60,6 +60,9 @@ class AuthProtocol(object): self.conf = conf self.app = app + """Handle 1.0 and 1.1 calls via middleware. + Right now Iam treating every call of 1.0 and 1.1 as call + to authenticate""" def __call__(self, env, start_response): """ Handle incoming request. Transform. And send downstream. """ self.start_response = start_response @@ -67,11 +70,10 @@ class AuthProtocol(object): self.request = Request(env) if self.request.path.startswith('/v1.0' ) or self.request.path.startswith('/v1.1'): - #Handle 1.0 and 1.1 calls via wrapper. params = {"passwordCredentials": {"username": utils.get_auth_user(self.request), "password": utils.get_auth_key(self.request)}} - + #Make request to keystone new_request = Request.blank('/v2.0/tokens') new_request.headers['Content-type'] = 'application/json' new_request.accept = 'text/json' @@ -89,18 +91,6 @@ class AuthProtocol(object): # Other calls pass to downstream WSGI component return self.app(self.env, self.start_response) - def get_auth_user(self): - auth_user = None - if "X-Auth-User" in self.request.headers: - auth_user = self.request.headers["X-Auth-User"] - return auth_user - - def get_auth_key(self): - auth_key = None - if "X-Auth-Key" in self.request.headers: - auth_key = self.request.headers["X-Auth-Key"] - return auth_key - def transform_keystone_auth_to_legacy_headers(self, content): headers = {} if "auth" in content: diff --git a/keystone/logic/types/auth.py b/keystone/logic/types/auth.py index 4b90b8ca..6e534adf 100755 --- a/keystone/logic/types/auth.py +++ b/keystone/logic/types/auth.py @@ -129,7 +129,7 @@ class AuthData(object): def to_xml(self): dom = etree.Element("auth", - xmlns="http://docs.openstack.org/identity/api/v2.0") + xmlns="http://docs.openstack.org/identity/api/v2.0") token = etree.Element("token", expires=self.token.expires.isoformat()) token.set("id", self.token.token_id) -- cgit From 4cf516ff36f7654fa42c24b83d1d87e3ea87fc31 Mon Sep 17 00:00:00 2001 From: Yogeshwar Srikrishnan Date: Thu, 9 Jun 2011 01:26:34 -0500 Subject: Minor fixes. --- bin/keystone | 2 +- keystone/logic/types/auth.py | 20 +++++++++++--------- 2 files changed, 12 insertions(+), 10 deletions(-) diff --git a/bin/keystone b/bin/keystone index decdfc51..483119f0 100755 --- a/bin/keystone +++ b/bin/keystone @@ -79,7 +79,7 @@ if __name__ == '__main__': admin_conf, admin_app = config.load_paste_app('admin', options, args) admin_server = wsgi.Server() admin_bind = options.get('admin_port') or admin_conf.get('bind_port') - if conf['server_bind_host'] == admin_bind: + if conf['server_bind_port'] == admin_bind: admin_bind += 1 admin_server.start(admin_app, int(admin_bind), admin_conf['bind_host']) diff --git a/keystone/logic/types/auth.py b/keystone/logic/types/auth.py index 6e534adf..c52c66da 100755 --- a/keystone/logic/types/auth.py +++ b/keystone/logic/types/auth.py @@ -144,14 +144,16 @@ class AuthData(object): if base_url.region: endpoint.set("region", base_url.region) if base_url.public_url: - endpoint.set("publicURL", base_url.public_url.replace( - '%tenant_id%', self.token.tenant_id)) + endpoint.set("publicURL", + base_url.public_url.replace('%tenant_id%',\ + self.token.tenant_id)) if base_url.admin_url: - endpoint.set("adminURL", base_url.admin_url.replace( - '%tenant_id%', self.token.tenant_id)) + endpoint.set("adminURL", + base_url.admin_url.replace('%tenant_id%',\ + self.token.tenant_id)) if base_url.internal_url: endpoint.set("internalURL", - base_url.internal_url.replace('%tenant_id%', + base_url.internal_url.replace('%tenant_id%',\ self.token.tenant_id)) service.append(endpoint) service_catalog.append(service) @@ -179,14 +181,14 @@ class AuthData(object): if base_url.region: endpoint["region"] = base_url.region if base_url.public_url: - endpoint["publicURL"] = base_url.public_url.replace( + endpoint["publicURL"] = base_url.public_url.replace( \ '%tenant_id%', self.token.tenant_id) if base_url.admin_url: - endpoint["adminURL"] = base_url.admin_url.replace( + endpoint["adminURL"] = base_url.admin_url.replace( \ '%tenant_id%', self.token.tenant_id) if base_url.internal_url: - endpoint["internalURL"] = base_url.internal_url.replace - ('%tenant_id%', self.token.tenant_id) + endpoint["internalURL"] = base_url.internal_url.\ + replace('%tenant_id%', self.token.tenant_id) endpoints.append(endpoint) service_catalog[key] = endpoints auth["serviceCatalog"] = service_catalog -- cgit From d99811e99b996dc05bd7a0d57a6bd7e380b4c20c Mon Sep 17 00:00:00 2001 From: Yogeshwar Srikrishnan Date: Thu, 9 Jun 2011 10:35:36 -0500 Subject: Name changes suggested by Ziad. --- bin/keystone-auth | 21 +++++++++++---------- etc/keystone.conf | 6 +++--- 2 files changed, 14 insertions(+), 13 deletions(-) mode change 100644 => 100755 etc/keystone.conf diff --git a/bin/keystone-auth b/bin/keystone-auth index 6159d3ab..179a0bef 100755 --- a/bin/keystone-auth +++ b/bin/keystone-auth @@ -49,23 +49,24 @@ if __name__ == '__main__': # Parse arguments and load config (options, args) = config.parse_options(parser) - debug = options.get('debug') or conf.get('debug', False) - debug = debug in [True, "True", "1"] - verbose = options.get('verbose') or conf.get('verbose', False) - verbose = verbose in [True, "True", "1"] - if debug or verbose: - config_file = config.find_config_file(options, args) - print "Using config file:", config_file # Start services try: # Load Service API server - conf, app = config.load_paste_app('server', options, args) + conf, app = config.load_paste_app('keystone-legacy-auth', options, args) + debug = options.get('debug') or conf.get('debug', False) + debug = debug in [True, "True", "1"] + verbose = options.get('verbose') or conf.get('verbose', False) + verbose = verbose in [True, "True", "1"] + if debug or verbose: + config_file = config.find_config_file(options, args) + print "Using config file:", config_file + server = wsgi.Server() server.start(app, int(conf['server_bind_port']), conf['server_bind_host']) - print "Service API listening on %s:%s" % (conf['bind_host'], - conf['bind_port']) + print "Service API listening on %s:%s" % (conf['server_bind_host'], + conf['server_bind_port']) server.wait() except RuntimeError, e: sys.exit("ERROR: %s" % e) diff --git a/etc/keystone.conf b/etc/keystone.conf old mode 100644 new mode 100755 index bcc33a09..7da598fc --- a/etc/keystone.conf +++ b/etc/keystone.conf @@ -50,9 +50,9 @@ paste.app_factory = keystone.server:app_factory [pipeline:keystone-legacy-auth] pipeline = - rackspace_legacy_auth + legacy_auth server -[filter:rackspace_legacy_auth] -paste.filter_factory = keystone.frontends.legacy_auth_frontend:filter_factory +[filter:legacy_auth] +paste.filter_factory = keystone.frontends.legacy_token_auth:filter_factory -- cgit From 26d9339b66d3d9ada590f4a8a6880f03083a82f2 Mon Sep 17 00:00:00 2001 From: Yogeshwar Srikrishnan Date: Thu, 9 Jun 2011 14:45:00 -0500 Subject: Rename file.Ziad suggestion. --- keystone/frontends/legacy_auth_frontend.py | 129 ----------------------------- keystone/frontends/legacy_token_auth.py | 129 +++++++++++++++++++++++++++++ 2 files changed, 129 insertions(+), 129 deletions(-) delete mode 100755 keystone/frontends/legacy_auth_frontend.py create mode 100644 keystone/frontends/legacy_token_auth.py diff --git a/keystone/frontends/legacy_auth_frontend.py b/keystone/frontends/legacy_auth_frontend.py deleted file mode 100755 index dcd03477..00000000 --- a/keystone/frontends/legacy_auth_frontend.py +++ /dev/null @@ -1,129 +0,0 @@ -#!/usr/bin/env python -# vim: tabstop=4 shiftwidth=4 softtabstop=4 -# -# Copyright (c) 2010-2011 OpenStack, LLC. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# Not Yet PEP8 standardized -""" -RACKSPACE LEGACY AUTH - STUB - -This WSGI component -- transforms rackspace auth header credentials to keystone credentials -and makes an authentication call on keystone.- transforms response it -receives into custom headers defined in properties and returns -the response. -""" -import os -import sys -import optparse -import httplib -import json -import ast - -from webob.exc import Request, Response -from paste.deploy import loadapp -from webob.exc import HTTPUnauthorized, HTTPInternalServerError - -POSSIBLE_TOPDIR = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]), - os.pardir, - os.pardir, - os.pardir)) -if os.path.exists(os.path.join(POSSIBLE_TOPDIR, 'keystone', '__init__.py')): - sys.path.insert(0, POSSIBLE_TOPDIR) - -import keystone -import keystone.utils as utils -from keystone.common import wsgi -from keystone.common import config - -PROTOCOL_NAME = "Legacy Authentication" - - -class AuthProtocol(object): - """Legacy Auth Middleware that handles authenticating client calls""" - - def __init__(self, app, conf): - """ Common initialization code """ - print "Starting the %s component" % PROTOCOL_NAME - self.conf = conf - self.app = app - - """Handle 1.0 and 1.1 calls via middleware. - Right now Iam treating every call of 1.0 and 1.1 as call - to authenticate""" - def __call__(self, env, start_response): - """ Handle incoming request. Transform. And send downstream. """ - self.start_response = start_response - self.env = env - self.request = Request(env) - if self.request.path.startswith('/v1.0' - ) or self.request.path.startswith('/v1.1'): - params = {"passwordCredentials": - {"username": utils.get_auth_user(self.request), - "password": utils.get_auth_key(self.request)}} - #Make request to keystone - new_request = Request.blank('/v2.0/tokens') - new_request.headers['Content-type'] = 'application/json' - new_request.accept = 'text/json' - new_request.body = json.dumps(params) - new_request.method = 'POST' - response = new_request.get_response(self.app) - #Handle failures. - if not str(response.status).startswith('20'): - return response(env, start_response) - headers = self.transform_keystone_auth_to_legacy_headers( - json.loads(response.body)) - resp = utils.send_legacy_result(204, headers) - return resp(env, start_response) - else: - # Other calls pass to downstream WSGI component - return self.app(self.env, self.start_response) - - def transform_keystone_auth_to_legacy_headers(self, content): - headers = {} - if "auth" in content: - auth = content["auth"] - if "token" in auth: - headers["X-Auth-Token"] = auth["token"]["id"] - if "serviceCatalog" in auth: - services = auth["serviceCatalog"] - service_mappings = ast.literal_eval( - self.conf["service-header-mappings"]) - for service in services: - service_name = service - service_urls = '' - for endpoint in services[service_name]: - if len(service_urls) > 0: - service_urls += ',' - service_urls += endpoint["publicURL"] - if len(service_urls) > 0: - if service_mappings.get(service_name): - headers[service_mappings.get( - service_name)] = service_urls - else: - #For Services that are not mapped, - #use X- prefix followed by service name. - headers['X-' + service_name.upper()] = service_urls - return headers - - -def filter_factory(global_conf, **local_conf): - """Returns a WSGI filter app for use with paste.deploy.""" - conf = global_conf.copy() - conf.update(local_conf) - - def auth_filter(app): - return AuthProtocol(app, conf) - return auth_filter diff --git a/keystone/frontends/legacy_token_auth.py b/keystone/frontends/legacy_token_auth.py new file mode 100644 index 00000000..dcd03477 --- /dev/null +++ b/keystone/frontends/legacy_token_auth.py @@ -0,0 +1,129 @@ +#!/usr/bin/env python +# vim: tabstop=4 shiftwidth=4 softtabstop=4 +# +# Copyright (c) 2010-2011 OpenStack, LLC. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# Not Yet PEP8 standardized +""" +RACKSPACE LEGACY AUTH - STUB + +This WSGI component +- transforms rackspace auth header credentials to keystone credentials +and makes an authentication call on keystone.- transforms response it +receives into custom headers defined in properties and returns +the response. +""" +import os +import sys +import optparse +import httplib +import json +import ast + +from webob.exc import Request, Response +from paste.deploy import loadapp +from webob.exc import HTTPUnauthorized, HTTPInternalServerError + +POSSIBLE_TOPDIR = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]), + os.pardir, + os.pardir, + os.pardir)) +if os.path.exists(os.path.join(POSSIBLE_TOPDIR, 'keystone', '__init__.py')): + sys.path.insert(0, POSSIBLE_TOPDIR) + +import keystone +import keystone.utils as utils +from keystone.common import wsgi +from keystone.common import config + +PROTOCOL_NAME = "Legacy Authentication" + + +class AuthProtocol(object): + """Legacy Auth Middleware that handles authenticating client calls""" + + def __init__(self, app, conf): + """ Common initialization code """ + print "Starting the %s component" % PROTOCOL_NAME + self.conf = conf + self.app = app + + """Handle 1.0 and 1.1 calls via middleware. + Right now Iam treating every call of 1.0 and 1.1 as call + to authenticate""" + def __call__(self, env, start_response): + """ Handle incoming request. Transform. And send downstream. """ + self.start_response = start_response + self.env = env + self.request = Request(env) + if self.request.path.startswith('/v1.0' + ) or self.request.path.startswith('/v1.1'): + params = {"passwordCredentials": + {"username": utils.get_auth_user(self.request), + "password": utils.get_auth_key(self.request)}} + #Make request to keystone + new_request = Request.blank('/v2.0/tokens') + new_request.headers['Content-type'] = 'application/json' + new_request.accept = 'text/json' + new_request.body = json.dumps(params) + new_request.method = 'POST' + response = new_request.get_response(self.app) + #Handle failures. + if not str(response.status).startswith('20'): + return response(env, start_response) + headers = self.transform_keystone_auth_to_legacy_headers( + json.loads(response.body)) + resp = utils.send_legacy_result(204, headers) + return resp(env, start_response) + else: + # Other calls pass to downstream WSGI component + return self.app(self.env, self.start_response) + + def transform_keystone_auth_to_legacy_headers(self, content): + headers = {} + if "auth" in content: + auth = content["auth"] + if "token" in auth: + headers["X-Auth-Token"] = auth["token"]["id"] + if "serviceCatalog" in auth: + services = auth["serviceCatalog"] + service_mappings = ast.literal_eval( + self.conf["service-header-mappings"]) + for service in services: + service_name = service + service_urls = '' + for endpoint in services[service_name]: + if len(service_urls) > 0: + service_urls += ',' + service_urls += endpoint["publicURL"] + if len(service_urls) > 0: + if service_mappings.get(service_name): + headers[service_mappings.get( + service_name)] = service_urls + else: + #For Services that are not mapped, + #use X- prefix followed by service name. + headers['X-' + service_name.upper()] = service_urls + return headers + + +def filter_factory(global_conf, **local_conf): + """Returns a WSGI filter app for use with paste.deploy.""" + conf = global_conf.copy() + conf.update(local_conf) + + def auth_filter(app): + return AuthProtocol(app, conf) + return auth_filter -- cgit From cfce057aaa01ed72bd84d53fe6e64b2e0f912f75 Mon Sep 17 00:00:00 2001 From: Jesse Andrews Date: Thu, 9 Jun 2011 19:02:12 -0700 Subject: set nova admin role if keystone user has "Admin" role --- keystone/auth_protocols/nova_auth_token.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/keystone/auth_protocols/nova_auth_token.py b/keystone/auth_protocols/nova_auth_token.py index e9d61b74..3a3221ec 100644 --- a/keystone/auth_protocols/nova_auth_token.py +++ b/keystone/auth_protocols/nova_auth_token.py @@ -61,6 +61,9 @@ class KeystoneAuthShim(wsgi.Middleware): user_ref = self.auth.get_user(user_id) except: user_ref = self.auth.create_user(user_id) + # set admin if user has admin role + if user_ref.is_admin() != (req.headers.get('X_ROLE', None) == 'Admin'): + self.auth.modify_user(user_ref, admin=req.headers.get('X_ROLE') == 'Admin') project_id = req.headers['X_TENANT'] try: project_ref = self.auth.get_project(project_id) -- cgit From 718e3094d503533ef4d2108522a6fa88b34384f8 Mon Sep 17 00:00:00 2001 From: Yogeshwar Srikrishnan Date: Fri, 10 Jun 2011 13:19:01 -0500 Subject: Doc updates. --- docs/guide/src/docbkx/identitydevguide.xml | 157 +++++++++++++++++++++++++++-- docs/guide/src/docbkx/samples/group.json | 1 + docs/guide/src/docbkx/samples/group.xml | 4 + docs/guide/src/docbkx/samples/groups.json | 1 + docs/guide/src/docbkx/samples/groups.xml | 5 + keystone/server.py | 4 +- 6 files changed, 163 insertions(+), 9 deletions(-) mode change 100644 => 100755 docs/guide/src/docbkx/identitydevguide.xml create mode 100644 docs/guide/src/docbkx/samples/group.json create mode 100644 docs/guide/src/docbkx/samples/group.xml create mode 100644 docs/guide/src/docbkx/samples/groups.json create mode 100644 docs/guide/src/docbkx/samples/groups.xml diff --git a/docs/guide/src/docbkx/identitydevguide.xml b/docs/guide/src/docbkx/identitydevguide.xml old mode 100644 new mode 100755 index 5af5c532..8cd562c6 --- a/docs/guide/src/docbkx/identitydevguide.xml +++ b/docs/guide/src/docbkx/identitydevguide.xml @@ -858,6 +858,49 @@ Host: identity.api.openstack.org/v1.1/
Core Admin API Proposal The following table of calls is proposed as core Keystone Admin APIs +
+ Users + + &LONG_URI_REFHEAD; + + + &POST; + /users + Get a list of users. + + + &GET; + /users/userId + Get a user. + + + &PUT; + /users/userId + Update a user. + + + &DELETE; + /users/userId + Delete a user. + + + &PUT; + /users/userId/password + Update a user password. + + + &PUT; + /users/userId/enabled + Enable/Disable user. + + + &PUT; + /users/userId/tenant + Update user tenant. + + + +
Tokens @@ -887,15 +930,65 @@ Host: identity.api.openstack.org/v1.1/ /tenants Get a list of tenants. - - &GET; - /tenants/tenantId - Get a tenant. - + + &GET; + /tenants/tenantId + Get a tenant. + + + &POST; + /tenants + Create a tenant. + + + &PUT; + /tenants/tenantId + Update a tenant. + + + &DELETE; + /tenants/tenantId + Delete a tenant. + + + &GET; + /tenants/tenantId/groups + Get a list of tenant groups. + + + &POST; + /tenants/tenantId/groups + Create a tenant group. + + + &GET; + /tenants/tenantId/groups/groupId + Get a tenant group with the specified id. + + + &PUT; + /tenants/tenantId/groups/groupId + Update a tenant group. + + + &GET; + /tenants/tenantId/groups/groupId/users + get tenant group users. + + + &PUT; + /tenants/tenantId/groups/groupId/users/userId + Add a user to a tenant group. + + + &DELETE; + /tenants/tenantId/groups/groupId/users/userId + Delete user tenant group. + -
- +
+
Endpoints (BaseURLs) @@ -1008,6 +1101,56 @@ Host: identity.api.openstack.org/v1.1/
+ +
+ Global Groups + + &LONG_URI_REFHEAD; + + + &POST; + /groups + Create a global group. + + + &GET; + /groups + Get a list of global groups. + + + &GET; + /groups/groupId + Get a global group. + + + &PUT; + /groups/groupId + Update a global group. + + + &DELETE; + /groups/groupId + Delete a global group. + + + &GET; + /groups/groupId/users + Get a list of users of a global group. + + + &PUT; + /groups/groupId/users/userId + Add user to a global group. + + + &DELETE; + /groups/groupId/users/userId + Delete user from a global group. + + + +
+ All other APIs listed in this section will be extensions used for this reference implementation of Keystone to support user and tenant management diff --git a/docs/guide/src/docbkx/samples/group.json b/docs/guide/src/docbkx/samples/group.json new file mode 100644 index 00000000..07dc0a10 --- /dev/null +++ b/docs/guide/src/docbkx/samples/group.json @@ -0,0 +1 @@ +{"group": {"id": "test_global_group", "description": "A description ..."}} \ No newline at end of file diff --git a/docs/guide/src/docbkx/samples/group.xml b/docs/guide/src/docbkx/samples/group.xml new file mode 100644 index 00000000..0f285307 --- /dev/null +++ b/docs/guide/src/docbkx/samples/group.xml @@ -0,0 +1,4 @@ + + + A Description of the group + diff --git a/docs/guide/src/docbkx/samples/groups.json b/docs/guide/src/docbkx/samples/groups.json new file mode 100644 index 00000000..06dd58a0 --- /dev/null +++ b/docs/guide/src/docbkx/samples/groups.json @@ -0,0 +1 @@ +{"groups": {"values": [{"id": "test_global_group_add", "description": "A description ..."}], "links": []}} \ No newline at end of file diff --git a/docs/guide/src/docbkx/samples/groups.xml b/docs/guide/src/docbkx/samples/groups.xml new file mode 100644 index 00000000..a429fdb3 --- /dev/null +++ b/docs/guide/src/docbkx/samples/groups.xml @@ -0,0 +1,5 @@ + + + A Description of the group + + diff --git a/keystone/server.py b/keystone/server.py index 8dff1159..139a47d8 100755 --- a/keystone/server.py +++ b/keystone/server.py @@ -533,7 +533,7 @@ class KeystoneAPI(wsgi.Router): db_api.configure_db(options) # Token Operations - auth_controller = AuthController(options) + auth_controller = AuthController(options) mapper.connect("/v2.0/tokens", controller=auth_controller, action="authenticate", conditions=dict(method=["POST"])) @@ -676,7 +676,7 @@ class KeystoneAdminAPI(wsgi.Router): controller=user_controller, action="set_user_password", conditions=dict(method=["PUT"])) - mapper.connect("/v1.0/tenants/{tenant_id}/users/{user_id}/add", + mapper.connect("/v2.0/tenants/{tenant_id}/users/{user_id}/add", controller=user_controller, action="add_user_tenant", conditions=dict(method=["PUT"])) -- cgit From d477f8b8ae14f8f9728bb6b108805940a6dade4d Mon Sep 17 00:00:00 2001 From: Yogeshwar Srikrishnan Date: Fri, 10 Jun 2011 13:38:48 -0500 Subject: Doc updates. --- docs/guide/src/docbkx/identitydevguide.xml | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/docs/guide/src/docbkx/identitydevguide.xml b/docs/guide/src/docbkx/identitydevguide.xml index 8cd562c6..ff85e1b1 100755 --- a/docs/guide/src/docbkx/identitydevguide.xml +++ b/docs/guide/src/docbkx/identitydevguide.xml @@ -864,7 +864,12 @@ Host: identity.api.openstack.org/v1.1/ &LONG_URI_REFHEAD; - &POST; + &PUT; + /users + Create a User. + + + &GET; /users Get a list of users. @@ -936,7 +941,7 @@ Host: identity.api.openstack.org/v1.1/ Get a tenant. - &POST; + &PUT; /tenants Create a tenant. @@ -985,6 +990,12 @@ Host: identity.api.openstack.org/v1.1/ /tenants/tenantId/groups/groupId/users/userId Delete user tenant group. + + &GET; + /tenants/tenantId/users + get tenant users. + + -- cgit From d6984f31b8b14a14d321605d7ec6c5b15612d844 Mon Sep 17 00:00:00 2001 From: Yogeshwar Srikrishnan Date: Fri, 10 Jun 2011 16:31:07 -0500 Subject: Doc updates.Minor keyston-manage changes. --- bin/keystone-manage | 20 ++- bin/sampledata.sh | 5 + docs/guide/src/docbkx/identitydevguide.xml | 211 ++++++++++++++++------------- 3 files changed, 142 insertions(+), 94 deletions(-) diff --git a/bin/keystone-manage b/bin/keystone-manage index 496d5337..582b7bf5 100755 --- a/bin/keystone-manage +++ b/bin/keystone-manage @@ -76,7 +76,7 @@ def Main(): parser.error('No object type specified for first argument') object_type = args[0] - if object_type in ['user', 'tenant', 'role', 'baseURLs' , 'token']: + if object_type in ['user', 'tenant', 'role', 'baseURLs' , 'token', 'tenant_baseURL']: pass else: parser.error('%s is not a supported object type' % object_type) @@ -309,6 +309,24 @@ def Main(): except Exception, e: print 'Error getting all BaseURLs:', str(e) return + elif object_type == "tenant_baseURL": + if command == "add": + if len(args) < 4: + parser.error("Missing arguments: baseURLs add 'tenant'\ + 'baseURL'") + + tenant_id = args[2] + baseURLs_id = args[3] + try: + object = db_models.TenantBaseURLAssociation() + object.tenant_id = tenant_id + object.baseURLs_id = baseURLs_id + object = db_api.baseurls_ref_add(object) + print "BaseURl Ref created successfully. ID=%s" % object.id + return + except Exception as exc: + print "ERROR: Failed to create BaseURL Ref: %s" % exc + return elif object_type == "token": if command == "add": if len(args) < 6: diff --git a/bin/sampledata.sh b/bin/sampledata.sh index 0238d36b..72117827 100755 --- a/bin/sampledata.sh +++ b/bin/sampledata.sh @@ -57,3 +57,8 @@ ./keystone-manage $* token add 999888777666 admin 1234 2015-02-05T00:00 ./keystone-manage $* token add 000999 admin 1234 2010-02-05T00:00 ./keystone-manage $* token add 999888777 disabled 1234 2015-02-05T00:00 + +#Tenant Role +./keystone-manage $*tenant_baseURL add 1234 1 +./keystone-manage $*tenant_baseURL add 1234 2 +./keystone-manage $*tenant_baseURL add 1234 3 \ No newline at end of file diff --git a/docs/guide/src/docbkx/identitydevguide.xml b/docs/guide/src/docbkx/identitydevguide.xml index ff85e1b1..e0e9ef11 100755 --- a/docs/guide/src/docbkx/identitydevguide.xml +++ b/docs/guide/src/docbkx/identitydevguide.xml @@ -133,15 +133,6 @@ and operators. Tenant administrators may assign roles to users. -
- Group - - A group of users. Groups may be used to organize and assign - privileges to a group of related users. For example, an operator - may create a "delinquent" group, which will assign limited - privileges to users who have past due bills. - -
General API Information @@ -955,41 +946,6 @@ Host: identity.api.openstack.org/v1.1/ /tenants/tenantId Delete a tenant. - - &GET; - /tenants/tenantId/groups - Get a list of tenant groups. - - - &POST; - /tenants/tenantId/groups - Create a tenant group. - - - &GET; - /tenants/tenantId/groups/groupId - Get a tenant group with the specified id. - - - &PUT; - /tenants/tenantId/groups/groupId - Update a tenant group. - - - &GET; - /tenants/tenantId/groups/groupId/users - get tenant group users. - - - &PUT; - /tenants/tenantId/groups/groupId/users/userId - Add a user to a tenant group. - - - &DELETE; - /tenants/tenantId/groups/groupId/users/userId - Delete user tenant group. - &GET; /tenants/tenantId/users @@ -1112,55 +1068,6 @@ Host: identity.api.openstack.org/v1.1/ - -
- Global Groups - - &LONG_URI_REFHEAD; - - - &POST; - /groups - Create a global group. - - - &GET; - /groups - Get a list of global groups. - - - &GET; - /groups/groupId - Get a global group. - - - &PUT; - /groups/groupId - Update a global group. - - - &DELETE; - /groups/groupId - Delete a global group. - - - &GET; - /groups/groupId/users - Get a list of users of a global group. - - - &PUT; - /groups/groupId/users/userId - Add user to a global group. - - - &DELETE; - /groups/groupId/users/userId - Delete user from a global group. - - - -
All other APIs listed in this section will be extensions used for this reference implementation of Keystone to support user and tenant management @@ -1830,4 +1737,122 @@ Host: identity.api.openstack.org/v1.1/
+ + + Appendix +
+ Rackspace Extenison Proposal +
+ Concepts + + The concepts that are specific to rackspace extensions are: + +
+ Group + + A group of users. Groups may be used to organize and assign + privileges to a group of related users. For example, an operator + may create a "delinquent" group, which will assign limited + privileges to users who have past due bills. + +
+
+ + The following table of calls is proposed as rackspace specific extensions for Keystone APIs + +
+ Global Groups + + &LONG_URI_REFHEAD; + + + &PUT; + /groups + Create a global group. + + + &GET; + /groups + Get a list of global groups. + + + &GET; + /groups/groupId + Get a global group. + + + &PUT; + /groups/groupId + Update a global group. + + + &DELETE; + /groups/groupId + Delete a global group. + + + &GET; + /groups/groupId/users + Get a list of users of a global group. + + + &PUT; + /groups/groupId/users/userId + Add user to a global group. + + + &DELETE; + /groups/groupId/users/userId + Delete user from a global group. + + + +
+
+ Tenant Groups + + &LONG_URI_REFHEAD; + + + &GET; + /tenants/tenantId/groups + Get a list of tenant groups. + + + &POST; + /tenants/tenantId/groups + Create a tenant group. + + + &GET; + /tenants/tenantId/groups/groupId + Get a tenant group with the specified id. + + + &PUT; + /tenants/tenantId/groups/groupId + Update a tenant group. + + + &GET; + /tenants/tenantId/groups/groupId/users + get tenant group users. + + + &PUT; + /tenants/tenantId/groups/groupId/users/userId + Add a user to a tenant group. + + + &DELETE; + /tenants/tenantId/groups/groupId/users/userId + Delete user tenant group. + + + +
+ +
+
+ -- cgit From 6c0f62e40057079a161e82f6ea0e67c4d8fc7b8a Mon Sep 17 00:00:00 2001 From: Ziad Sawalha Date: Fri, 10 Jun 2011 18:10:22 -0500 Subject: API v2.0 Proposal --- docs/guide/src/docbkx/identitydevguide.xml | 35 ++++++++++++++++------------- keystone/content/identitydevguide.pdf | Bin 285331 -> 298144 bytes 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/docs/guide/src/docbkx/identitydevguide.xml b/docs/guide/src/docbkx/identitydevguide.xml index e0e9ef11..cd4d4c9a 100755 --- a/docs/guide/src/docbkx/identitydevguide.xml +++ b/docs/guide/src/docbkx/identitydevguide.xml @@ -60,7 +60,7 @@ API v2.0 Keystone - OpenStack Identity - 2011-06-01 + 2011-06-10 Copyright details are filled in by the template. @@ -106,11 +106,18 @@ resources are accessible with it. A token may be revoked at anytime and is valid for a finite duration. + + While Keystone supports token-based authentication in this release, + the intention is for it to support additional protocols in the + future. The desire is to have it be an integration service, and not + a full-fledged identoty store and management solution. +
Tenant - Depending on the operator, a tenant may map to a customer, + A container used to group or isolate resources and/or identity + objects. Depending on the operator, a tenant may map to a customer, account, organization, or project.
@@ -118,12 +125,9 @@ User Users have a login and may be assigned tokens to access - resources. + resources. Users may be directly assigned to a particular tenant and + behave as if they are contained in that tenant. - - This is a Rackspace extensions to support a local identity store. - Extending this to work on any backing store is out of scope. -
Role @@ -731,11 +735,11 @@ Host: identity.api.openstack.org/v1.1/
Overview The operations described in this chapter allow clients to authenticate and get - access tokens and endpoints. + access tokens and service endpoints.
Core Service API Proposal - The following table of calls is proposed as code Keystone APIs + The following table of calls is proposed as core Keystone APIs &URI_REFHEAD; @@ -844,7 +848,7 @@ Host: identity.api.openstack.org/v1.1/
Overview The operations described in this chapter allow service developers to get and validate - access tokens, manage users, and manage tenants. + access tokens, manage users, tenants, roles, and service endpoints.
Core Admin API Proposal @@ -910,7 +914,7 @@ Host: identity.api.openstack.org/v1.1/ &DELETE; /tokens/tokenId - Revoke an existing token. + Revoke an existing token. @@ -949,7 +953,7 @@ Host: identity.api.openstack.org/v1.1/ &GET; /tenants/tenantId/users - get tenant users. + Get a tenant's users. @@ -1259,7 +1263,7 @@ Host: identity.api.openstack.org/v1.1/ &PUT; /tenants/tenantId - Update a tenant.. + Update a tenant. @@ -1745,7 +1749,7 @@ Host: identity.api.openstack.org/v1.1/
Concepts - The concepts that are specific to rackspace extensions are: + The concepts that are specific to Rackspace extensions are:
Group @@ -1758,7 +1762,8 @@ Host: identity.api.openstack.org/v1.1/
- The following table of calls is proposed as rackspace specific extensions for Keystone APIs + The following table of calls is proposed as Rackspace-specific + extensions for Keystone APIs in this version (2.0)
Global Groups diff --git a/keystone/content/identitydevguide.pdf b/keystone/content/identitydevguide.pdf index b3a7f978..fadf3c38 100644 Binary files a/keystone/content/identitydevguide.pdf and b/keystone/content/identitydevguide.pdf differ -- cgit From 7afbc306e28fb0d45cf15d8408bbac8ecffde8b5 Mon Sep 17 00:00:00 2001 From: gholt Date: Sat, 11 Jun 2011 04:06:34 +0000 Subject: Put updated Swift Quickstart into README.md --- README.md | 95 ++++++++++++++++++++++++++++++++++- docs/swift-quick-start.txt | 121 --------------------------------------------- 2 files changed, 93 insertions(+), 123 deletions(-) delete mode 100644 docs/swift-quick-start.txt diff --git a/README.md b/README.md index d9f2ed35..9a54febb 100644 --- a/README.md +++ b/README.md @@ -230,9 +230,100 @@ Initial support for using keystone as nova's identity component has been started Assuming you added the test data using bin/sampledata.sh, you can then use joeuser/secrete -## SWIFT Integration +## Swift Integration - Quick Start + +1. Install Swift, either from trunk or version 1.4.1 (once it's released) or + higher. Do the standard SAIO install with the included TempAuth to be sure + you have a working system to start with. This step is beyond the scope of + this quick start; see http://swift.openstack.org/development_saio.html for + a Swift development set up guide. Once you have a working Swift install, go + ahead and shut it down for now (the default Swift install uses the same + ports Keystone wants): + + $ swift-init all stop + +2. Obtain and install a source copy of Keystone: + + $ git clone https://github.com/rackspace/keystone.git ~/keystone + ... + $ cd ~/keystone && sudo python setup.py develop + ... + +3. Start up the Keystone service: + + $ cd ~/keystone/bin && ./keystone + Starting the Legacy Authentication component + Service API listening on 0.0.0.0:8080 + Admin API listening on 0.0.0.0:8081 + +4. In another window, edit the `~/keystone/bin/sampledata.sh` file, find the + `public.cloudfiles.com` text and replace it with the URL to your Swift + cluster using the following format (note that we're going to change Swift + to run on port 8888 later): `http://127.0.0.1:8888/v1/AUTH_%tenant_id%` + +5. Create the sample data entries: + + $ cd ~/keystone/bin && ./sampledata.sh + ... + +6. Reconfigure Swift's proxy server to use Keystone instead of TempAuth. + Here's an example `/etc/swift/proxy-server.conf`: + + [DEFAULT] + bind_port = 8888 + user = + + [pipeline:main] + pipeline = catch_errors cache keystone proxy-server + + [app:proxy-server] + use = egg:swift#proxy + account_autocreate = true + + [filter:keystone] + use = egg:keystone#tokenauth + auth_protocol = http + auth_host = 127.0.0.1 + auth_port = 8081 + admin_token = 999888777666 + delay_auth_decision = 0 + service_protocol = http + service_host = 127.0.0.1 + service_port = 8100 + service_pass = dTpw + + [filter:cache] + use = egg:swift#memcache + set log_name = cache + + [filter:catch_errors] + use = egg:swift#catch_errors + +7. Start Swift back up with the new configuration: + + $ swift-init main start + ... + +8. Use `st` to check everything works (note: you currently have to create a + container or upload something as your first action to have the account + created; there's a Swift bug to be fixed soon): + + $ st -A http://127.0.0.1:8080/v1.0 -U joeuser -K secrete post container + $ st -A http://127.0.0.1:8080/v1.0 -U joeuser -K secrete stat -v + StorageURL: http://127.0.0.1:8888/v1/AUTH_1234 + Auth Token: 74ce1b05-e839-43b7-bd76-85ef178726c3 + Account: AUTH_1234 + Containers: 1 + Objects: 0 + Bytes: 0 + Accept-Ranges: bytes + X-Trans-Id: tx25c1a6969d8f4372b63912f411de3c3b + +**Note: Keystone currently allows any valid token to do anything with any +account.** + +But, it works as a demo! -See swift-quick-start.txt in docs folder ## I want OpenStack (all of it) diff --git a/docs/swift-quick-start.txt b/docs/swift-quick-start.txt deleted file mode 100644 index f201327b..00000000 --- a/docs/swift-quick-start.txt +++ /dev/null @@ -1,121 +0,0 @@ -Quick Start to Integrating Swift and Keystone ---------------------------------------------- - -1. Install Swift with the included TempAuth. This step is beyond the scope of - this quick start; see http://swift.openstack.org/development_saio.html for - a Swift development set up guide. - -2. Obtain and install a source copy of Keystone:: - - git clone https://github.com/rackspace/keystone.git ~/keystone - cd ~/keystone && sudo python setup.py develop - -3. Move included configuration out of the way:: - - mv ~/keystone/etc ~/keystone/etc-orig - -4. Create /etc/keystone configuration directory:: - - sudo mkdir /etc/keystone - sudo chmod : /etc/keystone - -5. Create /etc/keystone/keystone.conf:: - - [DEFAULT] - verbose = True - debug = True - default_store = sqlite - log_file = /etc/keystone/keystone.log - sql_connection = sqlite:////etc/keystone/keystone.db - sql_idle_timeout = 30 - - [app:admin] - paste.app_factory = keystone.server:admin_app_factory - bind_host = 0.0.0.0 - bind_port = 8081 - - [app:server] - paste.app_factory = keystone.server:app_factory - bind_host = 0.0.0.0 - bind_port = 8080 - -6. Start up the Keystone service:: - - ~/keystone/bin/keystone - -7. Create the sample data entries:: - - cd ~/keystone/bin && ./sampledata.sh - -8. Configure Swift's proxy server to use Keystone instead of TempAuth. Here's - an example /etc/swift/proxy-server.conf:: - - [DEFAULT] - bind_port = 8888 - user = - - [pipeline:main] - pipeline = catch_errors cache keystone proxy-server - - [app:proxy-server] - use = egg:swift#proxy - allow_account_management = true - - [filter:keystone] - use = egg:keystone#tokenauth - auth_protocol = http - auth_host = 127.0.0.1 - auth_port = 8081 - admin_token = 999888777666 - delay_auth_decision = 0 - service_protocol = http - service_host = 127.0.0.1 - service_port = 8100 - service_pass = dTpw - - [filter:cache] - use = egg:swift#memcache - set log_name = cache - - [filter:catch_errors] - use = egg:swift#catch_errors - -9. Restart the Swift proxy to invoke the new configuration:: - - swift-init proxy restart - -10. Obtain an x-auth-token to use:: - - curl -i http://127.0.0.1:8080/v1.0 \ - -H 'x-auth-user: joeuser' -H 'x-auth-key: secrete' - -11. Create an account in Swift using the x-auth-token from above:: - - curl -X PUT http://127.0.0.1:8888/v1/joeuser \ - -H 'x-auth-token: ' - -12. Create a container in Swift:: - - curl -X PUT http://127.0.0.1:8888/v1/joeuser/container \ - -H 'x-auth-token: ' - -13. Upload an object:: - - curl -X PUT http://127.0.0.1:8888/v1/joeuser/container/object \ - -H 'x-auth-token: ' --data-binary 'test object' - -14. Do some listings:: - - curl http://127.0.0.1:8888/v1/joeuser -H 'x-auth-token: ' - curl http://127.0.0.1:8888/v1/joeuser/container \ - -H 'x-auth-token: ' - - -Notes ------ - -* Keystone does not yet return x-storage-url, so standard Swift tools won't - work yet. -* Keystone currently allows any valid token to do anything. - -But, it works as a demo! -- cgit From 38901ddcce5682d17e96764da37fab8ecfeb0c46 Mon Sep 17 00:00:00 2001 From: Ziad Sawalha Date: Sat, 11 Jun 2011 09:17:46 -0500 Subject: Update sample data and keystone-manage for local install of OpenStack --- bin/keystone-manage | 59 ++++++++++++++++++++++++++++++----------------------- bin/sampledata.sh | 4 ++-- 2 files changed, 36 insertions(+), 27 deletions(-) diff --git a/bin/keystone-manage b/bin/keystone-manage index 582b7bf5..df8d055b 100755 --- a/bin/keystone-manage +++ b/bin/keystone-manage @@ -124,9 +124,9 @@ def Main(): tenant = args[4] object.tenant_id = tenant db_api.user_create(object) - print "User created successfully. ID=%s" % object.id + print "SUCCESS: User %s created." % object.id except Exception as exc: - print "ERROR: Failed to create user: %s" % exc + print "ERROR: Failed to create user %s: %s" % (object_id, exc) return elif command == "disable": try: @@ -135,9 +135,9 @@ def Main(): raise IndexError("User %s not found" % object_id) object.enabled = False db_api.user_update(object_id, object) - print "User disabled: %s" % object.id + print "SUCCESS: User %s disabled." % object.id except Exception as exc: - print "ERROR: Failed to disable user: %s" % exc + print "ERROR: Failed to disable user %s: %s" % (object_id, exc) return elif command == "list": try: @@ -168,10 +168,10 @@ def Main(): object.id = object_id object.enabled = True db_api.tenant_create(object) - print "Tenant created successfully. ID=%s" % object.id + print "SUCCESS: Tenant %s created." % object.id return except Exception as exc: - print "ERROR: Failed to create tenant: %s" % exc + print "ERROR: Failed to create tenant %s: %s" % (object_id, exc) return elif command == "list": try: @@ -183,7 +183,7 @@ def Main(): for row in objects: print row.id, row.enabled except Exception, e: - print 'Error getting all users:', str(e) + print 'Error getting all users: %s', str(e) return elif command == "disable": try: @@ -192,9 +192,9 @@ def Main(): raise IndexError("Tenant %s not found" % object_id) object.enabled = False db_api.tenant_update(object_id, object) - print "Tenant disabled: %s" % object.id + print "SUCCESS: Tenant %s disabled." % object.id except Exception as exc: - print "ERROR: Failed to disable tenant: %s" % exc + print "ERROR: Failed to disable tenant %s: %s" % (object_id, exc) return elif object_type == "role": if command == "add": @@ -202,10 +202,10 @@ def Main(): object = db_models.Role() object.id = object_id db_api.role_create(object) - print "Role created successfully. ID=%s" % object.id + print "SUCCESS: Role %s created successfully." % object.id return except Exception as exc: - print "ERROR: Failed to create role: %s" % exc + print "ERROR: Failed to create role %s: %s" % (object_id, exc) return elif command == "list": if len(args) == 3: @@ -214,7 +214,8 @@ def Main(): objects = db_api.tenant_role_assignments_get(tenant) if objects == None: raise IndexError("Assignments not found") - print 'user', 'role' + print 'Role assignments for tenant %s' % tenant + print 'User', 'Role' print '-' * 20 for row in objects: print row.user_id, row.role_id @@ -228,7 +229,8 @@ def Main(): objects = db_api.role_get_all() if objects == None: raise IndexError("Roles not found") - print 'role' + print 'All roles' + print 'Role' print '-' * 20 for row in objects: print row.id @@ -251,15 +253,16 @@ def Main(): if tenant != None: object.tenant_id = tenant db_api.user_role_add(object) - print "Successfully granted %s the %s role on %s" %\ + print "SUCCESS: Granted %s the %s role on %s." %\ (object.user_id, object.role_id, object.tenant_id) except Exception as exc: - print "ERROR: Failed to grant role: %s" % exc + print "ERROR: Failed to grant role %s to %s on %s: %s" % (object_id, user, tenant, exc) return elif object_type == "baseURLs": if command == "add": if len(args) < 8: - parser.error("Missing arguments: baseURLs add 'region' 'service'"\ + parser.error("Missing arguments: baseURLs add " \ + "'region' 'service'" \ "'publicURL' 'adminURL' 'internalURL' 'enabled'") region = args[2] service = args[3] @@ -276,10 +279,12 @@ def Main(): object.internal_url = internal_url object.enabled = enabled object = db_api.baseurls_create(object) - print "BaseURl created successfully. ID=%s" % object.id + print "SUCCESS: Created BaseURL for %s pointing to %s." % \ + (object.service, object.public_url) return except Exception as exc: - print "ERROR: Failed to create BaseURLs: %s" % exc + print "ERROR: Failed to create BaseURL for %s: %s" % (service, + exc) return elif command == "list": if len(args) == 3: @@ -288,8 +293,9 @@ def Main(): objects = db_api.baseurls_ref_get_by_tenant(tenant) if objects == None: raise IndexError("URLs not found") + print 'Endpoints (BaseURLs) for tenant %s' % tenant print 'service', 'region', 'Public URL' - print '-' * 20 + print '-' * 30 for row in objects: print row.service, row.region, row.public_url except Exception, e: @@ -302,6 +308,7 @@ def Main(): objects = db_api.baseurls_get_all() if objects == None: raise IndexError("URLs not found") + print 'All Endpoints (BaseURLs)' print 'service', 'region', 'Public URL' print '-' * 20 for row in objects: @@ -322,7 +329,8 @@ def Main(): object.tenant_id = tenant_id object.baseURLs_id = baseURLs_id object = db_api.baseurls_ref_add(object) - print "BaseURl Ref created successfully. ID=%s" % object.id + print "SUCCESS: BaseURL %s added to tenant %s." % \ + (baseURLs_id, tenant_id) return except Exception as exc: print "ERROR: Failed to create BaseURL Ref: %s" % exc @@ -342,10 +350,10 @@ def Main(): "%Y%m%dT%H:%M") object.expires = tuple_time db_api.token_create(object) - print "Token created successfully. ID=%s" % object.token_id + print "SUCCESS: Token %s created." % object.token_id return except Exception as exc: - print "ERROR: Failed to create token: %s" % exc + print "ERROR: Failed to create token %s: %s" % (object_id, exc) return elif command == "list": try: @@ -366,13 +374,14 @@ def Main(): raise IndexError("Token %s not found" % object_id) else: db_api.token_delete(object_id) - print 'Token %s deleted' % object_id + print 'SUCCESS: Token %s deleted.' % object_id except Exception, e: - print 'Error deleting token %s:' % object_id, str(e) + print 'ERROR: Failed to delete token %s: %s' % \ + object_id, str(e) return # Command not handled - print ("Fail: %s %s not yet supported" % (object_type, command)) + print ("ERROR: %s %s not yet supported" % (object_type, command)) if __name__ == '__main__': diff --git a/bin/sampledata.sh b/bin/sampledata.sh index 72117827..1c58ae47 100755 --- a/bin/sampledata.sh +++ b/bin/sampledata.sh @@ -38,9 +38,9 @@ ./keystone-manage $* role grant Admin joeadmin ANOTHER:TENANT #BaseURLs -./keystone-manage $* baseURLs add DFW cloudFiles public.cloudfiles.com admin.cloudfiles.com internal.cloudfiles.com 1 +./keystone-manage $* baseURLs add DFW cloudFiles http://localhost:8888/v1/%tenant_id% admin.cloudfiles.com internal.cloudfiles.com 1 ./keystone-manage $* baseURLs add DFW cloudFilesCDN https://storage.clouddrive.com/v1/%tenant_id% https://storage.clouddrive.com/v1/%tenant_id% https://storage.clouddrive.com/v1/%tenant_id% 1 -./keystone-manage $* baseURLs add DFW cloudServers https://servers2.api.rackspacecloud.com/v1.0/%tenant_id% https://servers.api.rackspacecloud.com/v1.0/%tenant_id% https://servers.api.rackspacecloud.com/v1.0/%tenant_id% 1 +./keystone-manage $* baseURLs add DFW cloudServers http://localhost:8008/v1.0/%tenant_id% https://servers.api.rackspacecloud.com/v1.0/%tenant_id% https://servers.api.rackspacecloud.com/v1.0/%tenant_id% 1 # Groups #./keystone-manage $* group add Admin 1234 -- cgit From 23098315c530a01f1234bb0d4322116267170b1f Mon Sep 17 00:00:00 2001 From: Ziad Sawalha Date: Sat, 11 Jun 2011 10:32:41 -0500 Subject: Update to dev guide explaining admin call auth requirements --- docs/guide/src/docbkx/identitydevguide.xml | 53 ++++++++++++++++++++++++----- docs/guide/src/docbkx/samples/tenants.json | 5 +++ docs/guide/src/docbkx/samples/tenants.xml | 5 +++ keystone/content/identitydevguide.pdf | Bin 298144 -> 302544 bytes 4 files changed, 55 insertions(+), 8 deletions(-) diff --git a/docs/guide/src/docbkx/identitydevguide.xml b/docs/guide/src/docbkx/identitydevguide.xml index cd4d4c9a..f30cb51b 100755 --- a/docs/guide/src/docbkx/identitydevguide.xml +++ b/docs/guide/src/docbkx/identitydevguide.xml @@ -110,7 +110,7 @@ While Keystone supports token-based authentication in this release, the intention is for it to support additional protocols in the future. The desire is to have it be an integration service, and not - a full-fledged identoty store and management solution. + a full-fledged identity store and management solution.
@@ -824,19 +824,26 @@ Host: identity.api.openstack.org/v1.1/ serviceUnavailable(503) The operation returns a list of tenants which the caller has - access to. + access to. This call must be authenticated, so a valid token must + be passed in as a header. - &NO_REQUEST; - XML Tenants Response - - + Tenants Request with Auth Token + + + &NO_REQUEST; JSON Tenants Response + + + + XML Tenants Response + +
@@ -853,6 +860,36 @@ Host: identity.api.openstack.org/v1.1/
Core Admin API Proposal The following table of calls is proposed as core Keystone Admin APIs + +
+ Admin Access + Most calls on the Admin API require authentication. The only calls available without authentication are the calls to discover the service (getting version info, WADL contract, dev guide, help, etc…) and the call to authenticate and get a token. + +Authentication is performed by passing in a valid token in the X-Auth-Token header on the request from the client. +Keystone will verify the token has (or belongs to a user that has) the Admin role. + + + See the readme file or administrator guides for how to bootstrap Keystone and create your first administrator. + + + + + + + + + + + + + + + + + +
Authentication Header
Header TypeNameValue
HTTP/1.1 RequestX-Auth-Tokentxfa8426a08eaf
+
+
Users @@ -1841,7 +1878,7 @@ Host: identity.api.openstack.org/v1.1/ &GET; /tenants/tenantId/groups/groupId/users - get tenant group users. + List tenant group users. &PUT; @@ -1851,7 +1888,7 @@ Host: identity.api.openstack.org/v1.1/ &DELETE; /tenants/tenantId/groups/groupId/users/userId - Delete user tenant group. + Remove user from tenant group. diff --git a/docs/guide/src/docbkx/samples/tenants.json b/docs/guide/src/docbkx/samples/tenants.json index 7fb848f7..a2fa2608 100644 --- a/docs/guide/src/docbkx/samples/tenants.json +++ b/docs/guide/src/docbkx/samples/tenants.json @@ -1,3 +1,8 @@ +HTTP/1.1 200 OK +Content-Type: application/json; charset=UTF-8 +Content-Length: 100 +Date: Sun, 1 Jan 2011 9:00:00 GMT + {"tenants": { "values" : [ { diff --git a/docs/guide/src/docbkx/samples/tenants.xml b/docs/guide/src/docbkx/samples/tenants.xml index cda2f662..2a9e9c3b 100644 --- a/docs/guide/src/docbkx/samples/tenants.xml +++ b/docs/guide/src/docbkx/samples/tenants.xml @@ -1,3 +1,8 @@ +HTTP/1.1 200 OK +Content-Type: application/xml; charset=UTF-8 +Content-Length: 200 +Date: Sun, 1 Jan 2011 9:00:00 GMT + diff --git a/keystone/content/identitydevguide.pdf b/keystone/content/identitydevguide.pdf index fadf3c38..2113e625 100644 Binary files a/keystone/content/identitydevguide.pdf and b/keystone/content/identitydevguide.pdf differ -- cgit From ffd0e032060d5c5c407a50156bf0b0f76d99e57b Mon Sep 17 00:00:00 2001 From: Ziad Sawalha Date: Sat, 11 Jun 2011 12:09:18 -0500 Subject: Updated SWIFT endpoint default --- bin/sampledata.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bin/sampledata.sh b/bin/sampledata.sh index 1c58ae47..46135dd2 100755 --- a/bin/sampledata.sh +++ b/bin/sampledata.sh @@ -38,7 +38,7 @@ ./keystone-manage $* role grant Admin joeadmin ANOTHER:TENANT #BaseURLs -./keystone-manage $* baseURLs add DFW cloudFiles http://localhost:8888/v1/%tenant_id% admin.cloudfiles.com internal.cloudfiles.com 1 +./keystone-manage $* baseURLs add DFW cloudFiles http://127.0.0.1:8888/v1/AUTH_%tenant_id% admin.cloudfiles.com internal.cloudfiles.com 1 ./keystone-manage $* baseURLs add DFW cloudFilesCDN https://storage.clouddrive.com/v1/%tenant_id% https://storage.clouddrive.com/v1/%tenant_id% https://storage.clouddrive.com/v1/%tenant_id% 1 ./keystone-manage $* baseURLs add DFW cloudServers http://localhost:8008/v1.0/%tenant_id% https://servers.api.rackspacecloud.com/v1.0/%tenant_id% https://servers.api.rackspacecloud.com/v1.0/%tenant_id% 1 -- cgit From 67a3b6aa7f0482e86fbb4a077230cc6b35179bad Mon Sep 17 00:00:00 2001 From: Ziad Sawalha Date: Sat, 11 Jun 2011 16:03:49 -0500 Subject: Moved tests to keystone folder and removed old management tools - issue #26 --- test/EchoSOAPUI.xml | 2 - test/IdentitySOAPUI.xml | 1355 ------------------------------- test/__init__.py | 0 test/functional/base.py | 77 -- test/functional/ksapi.py | 146 ---- test/functional/run_tests.py | 63 -- test/functional/sample_test.py | 85 -- test/functional/simplerest.py | 641 --------------- test/functional/test_tokens.py | 51 -- test/kill.sql | 10 - test/unit/__init__.py | 0 test/unit/base.py | 282 ------- test/unit/decorators.py | 49 -- test/unit/test_BaseURLs.py | 667 ---------------- test/unit/test_auth.py | 34 - test/unit/test_authentication.py | 215 ----- test/unit/test_authn_v2.py | 463 ----------- test/unit/test_common.py | 809 ------------------- test/unit/test_exthandler.py | 65 -- test/unit/test_groups.py | 966 ---------------------- test/unit/test_keystone.py | 60 -- test/unit/test_roles.py | 682 ---------------- test/unit/test_server.py | 86 -- test/unit/test_tenant_groups.py | 1217 ---------------------------- test/unit/test_tenants.py | 661 ---------------- test/unit/test_token.py | 173 ---- test/unit/test_users.py | 1584 ------------------------------------- test/unit/test_version.py | 49 -- tools/management/delgroup.py | 54 -- tools/management/getgroup.py | 52 -- tools/management/getgroups.py | 49 -- tools/management/getgroupusers.py | 51 -- tools/management/getuser.py | 49 -- tools/management/getusergroups.py | 50 -- tools/management/groupadd.py | 52 -- tools/management/setuserlock.py | 61 -- tools/management/setuserpswd.py | 53 -- tools/management/updategroup.py | 54 -- tools/management/userdel.py | 51 -- tools/management/userupdate.py | 53 -- 40 files changed, 11121 deletions(-) delete mode 100644 test/EchoSOAPUI.xml delete mode 100644 test/IdentitySOAPUI.xml delete mode 100644 test/__init__.py delete mode 100644 test/functional/base.py delete mode 100644 test/functional/ksapi.py delete mode 100755 test/functional/run_tests.py delete mode 100644 test/functional/sample_test.py delete mode 100644 test/functional/simplerest.py delete mode 100644 test/functional/test_tokens.py delete mode 100644 test/kill.sql delete mode 100644 test/unit/__init__.py delete mode 100644 test/unit/base.py delete mode 100644 test/unit/decorators.py delete mode 100644 test/unit/test_BaseURLs.py delete mode 100644 test/unit/test_auth.py delete mode 100755 test/unit/test_authentication.py delete mode 100644 test/unit/test_authn_v2.py delete mode 100755 test/unit/test_common.py delete mode 100644 test/unit/test_exthandler.py delete mode 100644 test/unit/test_groups.py delete mode 100644 test/unit/test_keystone.py delete mode 100644 test/unit/test_roles.py delete mode 100644 test/unit/test_server.py delete mode 100644 test/unit/test_tenant_groups.py delete mode 100644 test/unit/test_tenants.py delete mode 100644 test/unit/test_token.py delete mode 100644 test/unit/test_users.py delete mode 100644 test/unit/test_version.py delete mode 100755 tools/management/delgroup.py delete mode 100755 tools/management/getgroup.py delete mode 100755 tools/management/getgroups.py delete mode 100755 tools/management/getgroupusers.py delete mode 100755 tools/management/getuser.py delete mode 100755 tools/management/getusergroups.py delete mode 100755 tools/management/groupadd.py delete mode 100755 tools/management/setuserlock.py delete mode 100755 tools/management/setuserpswd.py delete mode 100755 tools/management/updategroup.py delete mode 100755 tools/management/userdel.py delete mode 100755 tools/management/userupdate.py diff --git a/test/EchoSOAPUI.xml b/test/EchoSOAPUI.xml deleted file mode 100644 index 8a74eee0..00000000 --- a/test/EchoSOAPUI.xml +++ /dev/null @@ -1,2 +0,0 @@ - -http://localhost:8090X-Auth-TokenHEADERxs:string*/*application/xml200v1:echoapplication/json200<xml-fragment/>http://localhost:8090*/*application/xml200v1:echoapplication/json200http://localhost:8090*/*application/xml200v1:echoapplication/json200http://localhost:8090*/*application/xml200v1:echoapplication/json200http://localhost:8090*/*application/xml200v1:echoapplication/json200http://localhost:8090*/*application/xml200v1:echoapplication/json200http://localhost:8090 \ No newline at end of file diff --git a/test/IdentitySOAPUI.xml b/test/IdentitySOAPUI.xml deleted file mode 100644 index 3cf2984e..00000000 --- a/test/IdentitySOAPUI.xml +++ /dev/null @@ -1,1355 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -]]>file:/Users/jorgew/projects/keystone/keystone/identity.wadl - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -]]>http://wadl.dev.java.net/2009/02file:/Users/jorgew/projects/keystone/keystone/xsd/api.xsd<schema elementFormDefault="qualified" attributeFormDefault="unqualified" targetNamespace="http://docs.openstack.org/identity/api/v2.0" xmlns="http://www.w3.org/2001/XMLSchema" xmlns:identity="http://docs.openstack.org/identity/api/v2.0" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> - <include schemaLocation="token.xsd"/> - <include schemaLocation="tenant.xsd"/> - <include schemaLocation="fault.xsd"/> -</schema>http://www.w3.org/2001/XMLSchemafile:/Users/jorgew/projects/keystone/keystone/xsd/token.xsd - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -]]>http://www.w3.org/2001/XMLSchemafile:/Users/jorgew/projects/keystone/keystone/xsd/tenant.xsd - - - - - - - - - - - - - - - - - - - - - - - -]]>http://www.w3.org/2001/XMLSchemafile:/Users/jorgew/projects/keystone/keystone/xsd/atom/atom.xsd - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - See section 3.4 of the ATOM RFC - RFC4287 - - - - - - - TODO - - - - - - - TODO - - - - - - - TODO - - - - - - - TODO - - - - - - - TODO - - - - - - -]]>http://www.w3.org/2001/XMLSchemafile:/Users/jorgew/projects/keystone/keystone/xsd/atom/xml.xsd - - - -
-

About the XML namespace

-
-

This schema document describes the XML namespace, in a form - suitable for import by other schema documents.

-

- See - http://www.w3.org/XML/1998/namespace.html - and - http://www.w3.org/TR/REC-xml - for information - about this namespace. -

-

Note that local names in this namespace are intended to be - defined only by the World Wide Web Consortium or its subgroups. - The names currently defined in this namespace are listed below. - They should not be used with conflicting semantics by any Working - Group, specification, or document instance.

-

- See further below in this document for more information about - how to refer to this schema document from your own - XSD schema documents - and about - the - namespace-versioning policy governing this schema document - . -

-
-
-
-
- - - -
-

lang (as an attribute name)

-

denotes an attribute whose value - is a language code for the natural language of the content of - any element; its value is inherited. This name is reserved - by virtue of its definition in the XML specification.

-
-
-

Notes

-

Attempting to install the relevant ISO 2- and 3-letter - codes as the enumerated possible values is probably never - going to be a realistic possibility.

-

- See BCP 47 at - http://www.rfc-editor.org/rfc/bcp/bcp47.txt - and the IANA language subtag registry at - http://www.iana.org/assignments/language-subtag-registry - for further information. -

-

The union allows for the 'un-declaration' of xml:lang with - the empty string.

-
-
-
- - - - - - - - - -
- - - -
-

space (as an attribute name)

-

denotes an attribute whose - value is a keyword indicating what whitespace processing - discipline is intended for the content of the element; its - value is inherited. This name is reserved by virtue of its - definition in the XML specification.

-
-
-
- - - - - - -
- - - -
-

base (as an attribute name)

-

denotes an attribute whose value - provides a URI to be used as the base for interpreting any - relative URIs in the scope of the element on which it - appears; its value is inherited. This name is reserved - by virtue of its definition in the XML Base specification.

-

- See - http://www.w3.org/TR/xmlbase/ - for information about this attribute. -

-
-
-
-
- - - -
-

id (as an attribute name)

-

denotes an attribute whose value - should be interpreted as if declared to be of type ID. - This name is reserved by virtue of its definition in the - xml:id specification.

-

- See - http://www.w3.org/TR/xml-id/ - for information about this attribute. -

-
-
-
-
- - - - - - - - -
-

Father (in any context at all)

-
-

denotes Jon Bosak, the chair of - the original XML Working Group. This name is reserved by - the following decision of the W3C XML Plenary and - XML Coordination groups:

-
-

In appreciation for his vision, leadership and - dedication the W3C XML Plenary on this 10th day of - February, 2000, reserves for Jon Bosak in perpetuity - the XML name "xml:Father".

-
-
-
-
-
- - -
-

- About this schema document -

-
-

- This schema defines attributes and an attribute group suitable - for use by schemas wishing to allow - xml:base - , - xml:lang - , - xml:space - or - xml:id - attributes on elements they define. -

-

To enable this, such a schema must import this schema for - the XML namespace, e.g. as follows:

-
<schema . . .>
-           . . .
-           <import namespace="http://www.w3.org/XML/1998/namespace"
-                      schemaLocation="http://www.w3.org/2001/xml.xsd"/>
-

or

-
<import namespace="http://www.w3.org/XML/1998/namespace"
-                      schemaLocation="http://www.w3.org/2009/01/xml.xsd"/>
-

Subsequently, qualified reference to any of the attributes or the - group defined below will have the desired effect, e.g.

-
<type . . .>
-           . . .
-           <attributeGroup ref="xml:specialAttrs"/>
-

will define a type which will schema-validate an instance element - with any of those attributes.

-
-
-
-
- - -
-

- Versioning policy for this schema document -

-
-

- In keeping with the XML Schema WG's standard versioning - policy, this schema document will persist at - http://www.w3.org/2009/01/xml.xsd - . -

-

- At the date of issue it can also be found at - http://www.w3.org/2001/xml.xsd - . -

-

- The schema document at that URI may however change in the future, - in order to remain compatible with the latest version of XML - Schema itself, or with the XML namespace itself. In other words, - if the XML Schema or XML namespaces change, the version of this - document at - http://www.w3.org/2001/xml.xsd - will change accordingly; the version at - http://www.w3.org/2009/01/xml.xsd - will not change. -

-

Previous dated (and unchanging) versions of this schema - document are at:

- -
-
-
-
-
]]>
http://www.w3.org/2001/XMLSchema
file:/Users/jorgew/projects/keystone/keystone/xsd/fault.xsd - - - - - - - - - - - - - - - - -

A human readable message that is appropriate for display - to the end user.

-
-
-
- - - -

The optional <details> element may contain useful - information for tracking down errors (e.g a stack - trace). This information may or may not be appropriate - for display to an end user.

-
-
-
- -
- - - -

The HTTP status code associated with the current fault.

-
-
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -

An optional dateTime denoting when an operation should - be retried.

-
-
-
-
-
-
-]]>
http://www.w3.org/2001/XMLSchema
file:/Users/jorgew/projects/keystone/keystone/xsd/api-common.xsd - - - - - Open Stack Common API Schema Types 1.0 - - - - - -

This is the main index XML Schema document - for Common API Schema Types Version 1.0.

-
-
- - - -

Types related to extensions.

-
-
-
- - - -

Types related to API version details.

-
-
-
-
]]>
http://www.w3.org/2001/XMLSchema
file:/Users/jorgew/projects/keystone/keystone/xsd/extensions.xsd - - - - - - - - - - - - - - - - - - - - - - - - - -

There should be at least one atom link - with a describedby relation.

-
-
-
-
- - - - - -]]>
http://www.w3.org/2001/XMLSchema
file:/Users/jorgew/projects/keystone/keystone/xsd/version.xsd - - - - - - - - - - - - - The VersionStatus type describes a service's operational status. - - - - - - - - - - - - - A version choice list outlines a collection of service version choices. - - - - - - - - - - - In version lists, every single version must - contain at least one self link. - - - - - - - - - - - When used as a root element, a version choice - must contain at least one describedby link. - - - - - - - - - - A version choice contains relevant information about an available service - that a user can then use to target a specific version of the service. Note - that both the descriptive media types and the atom link references are - not manditory and are offered as message enrichment elements rather - than message requirements. - - - - - - - - - - - The ID of a version choice represents the service version's unique - identifier. This ID is guaranteed to be unique only among the - service version choices outlined in the VersionChoiceList. - - - - - - - A version choice's status describes the current operational state of - the given service version. The operational status is captured in a - simple type enumeration called VersionStatus. - - - - - - - - A version choice's updated attribute describes - the time when the version was updated. The - time should be updated anytime - anything - in the - version has changed: documentation, - extensions, bug fixes. - - - - - - - - - - A MediaTypeList outlines a collection of valid media types for a given - service version. - - - - - - - - - - - - A MediaType describes what content types the service version understands. - - - - - - - - - The base of a given media type describes the simple MIME type - that then a more complicated media type can be derived from. These - types are basic and provide no namespace or version specific - data are are only provided as a convenience. Because of this the - base attribute is declared as optional. - - - - - - - - The type attribute of a MediaType describes the MIME specific - identifier of the media type in question. This identifier should include - a vendor namespace ( - See RFC 2048 - ) - as well as a version suffix. - - - - - - -]]>http://www.w3.org/2001/XMLSchema
http://localhost:8080aliasTEMPLATExs:stringapplication/xml200 203v1:extensionapplication/json200 203application/xml400v1:badRequestapplication/xml404v1:itemNotFoundapplication/xml500v1:identityFaultapplication/xml503v1:serviceUnavailableapplication/json400 404 500 503<xml-fragment/>http://localhost:8080application/xml200 203v1:extensionsapplication/json200 203application/xml400v1:badRequestapplication/xml500v1:identityFaultapplication/xml503v1:serviceUnavailableapplication/json400 500 503<xml-fragment/>http://localhost:8080X-Auth-TokenHEADERxs:stringtokenIdTEMPLATExs:stringbelongsToQUERYxs:stringapplication/xml200 203v1:authapplication/json200 203application/xml401v1:unauthorizedapplication/xml403v1:forbiddenapplication/xml403v1:userDisabledapplication/xml400v1:badRequestapplication/xml404v1:itemNotFoundapplication/xml500v1:identityFaultapplication/xml503v1:serviceUnavailableapplication/json400 401 403 404 500 503<xml-fragment/>http://localhost:8080 - - - -application/xml401v1:unauthorizedapplication/xml403v1:forbiddenapplication/xml400v1:badRequestapplication/xml404v1:itemNotFoundapplication/xml500v1:identityFaultapplication/xml503v1:serviceUnavailableapplication/json400 401 403 404 500 503<xml-fragment/>http://localhost:8080 - - -application/xmlv1:passwordCredentialsapplication/jsonapplication/xml200 -203v1:authapplication/json200 -203application/xml401v1:unauthorizedapplication/xml403v1:userDisabledapplication/xml400v1:badRequestapplication/xml500v1:identityFaultapplication/xml503v1:serviceUnavailableapplication/json401 -403 400 500 503<xml-fragment/>http://localhost:8080<passwordCredentials -password="secrete" username="joeuser" -xmlns="http://docs.openstack.org/identity/api/v2.0"/>X-Auth-TokenHEADERxs:stringtenantIdTEMPLATExs:stringapplication/xml200 -203v1:tenantapplication/json200 -203application/xml401v1:unauthorizedapplication/xml403v1:forbiddenapplication/xml400v1:badRequestapplication/xml404v1:itemNotFoundapplication/xml500v1:identityFaultapplication/xml503v1:serviceUnavailableapplication/json400 -401 403 404 500 503<xml-fragment/>http://localhost:8080 - - -application/xmlv1:tenantapplication/jsonapplication/xml200v1:tenantapplication/json200application/xml401v1:unauthorizedapplication/xml403v1:forbiddenapplication/xml404v1:itemNotFoundapplication/xml400v1:badRequestapplication/xml500v1:identityFaultapplication/xml503v1:serviceUnavailableapplication/json401 -403 404 400 500 503<xml-fragment/>http://localhost:8080<v1:tenant enabled="true" xmlns:v1="http://docs.openstack.org/identity/api/v2.0"> - <v1:description>New Description</v1:description> -</v1:tenant> - - -application/xml401v1:unauthorizedapplication/xml403v1:forbiddenapplication/xml400v1:badRequestapplication/xml404v1:itemNotFoundapplication/xml500v1:identityFaultapplication/xml503v1:serviceUnavailableapplication/json400 -401 403 404 500 503<entry key="Accept" value="application/xml" xmlns="http://eviware.com/soapui/config"/>http://localhost:8080 - - -markerQUERYxs:stringlimitQUERYxs:intapplication/xml200 -203v1:tenantsapplication/json200 -203application/xml401v1:unauthorizedapplication/xml403v1:forbiddenapplication/xml400v1:badRequestapplication/xml404v1:itemNotFoundapplication/xml500v1:identityFaultapplication/xml503v1:serviceUnavailableapplication/json400 -401 403 404 500 503<xml-fragment/>http://localhost:8080application/xmlv1:tenantapplication/jsonapplication/xml201v1:tenantapplication/json201application/xml401v1:unauthorizedapplication/xml403v1:forbiddenapplication/xml -409v1:tenantConflictapplication/xml -400v1:badRequestapplication/xml500v1:identityFaultapplication/xml503v1:serviceUnavailableapplication/json401 -403 400 409 500 503<xml-fragment/>http://localhost:8080<v1:tenant -enabled="true" id="my_new_tenant" -xmlns:v1="http://docs.openstack.org/identity/api/v2.0"><v1:description>This -is a description of my tenant. Thank you very -much.</v1:description></v1:tenant>application/xml200 -203v1:versionapplication/json200 -203application/xml400v1:badRequestapplication/xml500v1:identityFaultapplication/xml503v1:serviceUnavailableapplication/json400 -500 503<xml-fragment/>http://localhost:8080
SEQUENTIAL<xml-fragment/>http://localhost:8080authfalsefalsetokenfalsefalseuserfalsefalse - - - -<xml-fragment/>http://localhost:8080unauthorizedfalsefalse401falsefalse - - - -<xml-fragment/>http://localhost:8080unauthorizedfalsefalse401falsefalse - - - -<xml-fragment/>http://localhost:8080unauthorizedfalsefalse401falsefalse - - - -<xml-fragment/>http://localhost:8080forbiddenfalsefalse403falsefalse - - - -<xml-fragment/>http://localhost:8080userDisabledfalsefalse403falsefalse - - - -<xml-fragment/>http://localhost:8080authfalsefalsetokenfalsefalseuserfalsefalse - - - -<xml-fragment/>http://localhost:8080authfalsefalsetokenfalsefalseuserfalsefalse - - -<xml-fragment/>http://localhost:8080itemNotFoundfalsefalse404falsefalse - - - -<xml-fragment/>http://localhost:8080itemNotFoundfalsefalse404falsefalse - - -<xml-fragment/>http://localhost:8080itemNotFoundfalsefalse404falsefalse - - -<xml-fragment/>http://localhost:8080<passwordCredentials password="P@ssword1" username="testuser" xmlns="http://docs.openstack.org/identity/api/v2.0"/>401falsefalseunauthorizedfalsefalse<xml-fragment/>http://localhost:8080<passwordCredentials password="1234" username="disabled" xmlns="http://docs.openstack.org/identity/api/v2.0"/>403falsefalseuserDisabledfalsefalse<xml-fragment/>http://localhost:8080<passwordCredentials password="123774" username="joeuser" xmlns="http://docs.openstack.org/identity/api/v2.0"/>401falsefalseunauthorizedfalsefalse<xml-fragment/>http://localhost:8080<passwordCredentials password="secrete" username="admin" xmlns="http://docs.openstack.org/identity/api/v2.0"/>userfalsefalsetokenfalsefalseAdminfalsefalsedeclare namespace auth='http://docs.openstack.org/identity/api/v2.0'; -/auth:auth/auth:user/auth:groups/auth:group/@id='Admin'truefalsefalse<xml-fragment/>http://localhost:8080<passwordCredentials password="secrete" username="joeuser" xmlns="http://docs.openstack.org/identity/api/v2.0"/>userfalsefalsetokenfalsefalseAdminfalsefalsedeclare namespace auth='http://docs.openstack.org/identity/api/v2.0'; -/auth:auth/auth:user/auth:groups/auth:group/@id='Admin'falsefalsefalse<xml-fragment/>http://localhost:8080{ - "passwordCredentials" : { - "username" : "testuser", - "password" : "P@ssword1" - } -}401falsefalseunauthorizedfalsefalse<xml-fragment/>http://localhost:8080{ - "passwordCredentials" : { - "username" : "disabled", - "password" : "1234" - } -}403falsefalseuserDisabledfalsefalse<xml-fragment/>http://localhost:8080{ - "passwordCredentials" : { - "username" : "joeuser", - "password" : "123774" - } -}401falsefalseunauthorizedfalsefalse<xml-fragment/>http://localhost:8080{ - "passwordCredentials" : { - "username" : "admin", - "password" : "secrete" - } -}userfalsefalsetokenfalsefalseAdminfalsefalse<xml-fragment/>http://localhost:8080{ - "passwordCredentials" : { - "username" : "joeuser", - "password" : "secrete" - } -}userfalsefalsetokenfalsefalseAdminfalsefalse<entry key="Accept" value="application/xml" xmlns="http://eviware.com/soapui/config"/>http://localhost:8080404falsefalseitemNotFoundfalsefalse - - -<xml-fragment/>http://localhost:8080<passwordCredentials password="secrete" username="joeuser" xmlns="http://docs.openstack.org/identity/api/v2.0"/>userfalsefalsetokenfalsefalseAdminfalsefalsedeclare namespace auth='http://docs.openstack.org/identity/api/v2.0'; -/auth:auth/auth:user/auth:groups/auth:group/@id='Admin'falsefalsefalsedeclare namespace auth='http://docs.openstack.org/identity/api/v2.0'; -/auth:auth/auth:token/@id887665443383838falsefalse<entry key="Accept" value="application/xml" xmlns="http://eviware.com/soapui/config"/>http://localhost:8080assert(context.response==null) - - -<xml-fragment/>http://localhost:8080itemNotFoundfalsefalse404falsefalse - - -<xml-fragment/>http://localhost:8080<passwordCredentials password="secrete" username="joeuser" xmlns="http://docs.openstack.org/identity/api/v2.0"/>userfalsefalsetokenfalsefalseAdminfalsefalsedeclare namespace auth='http://docs.openstack.org/identity/api/v2.0'; -/auth:auth/auth:user/auth:groups/auth:group/@id='Admin'falsefalsefalsedeclare namespace auth='http://docs.openstack.org/identity/api/v2.0'; -/auth:auth/auth:token/@id="887665443383838"falsefalsefalse<xml-fragment/>http://localhost:8080<v1:tenant enabled="true" id="my_new_tenant" xmlns:v1="http://docs.openstack.org/identity/api/v2.0"><v1:description>This is a description of my tenant. Thank you very much.</v1:description></v1:tenant>declare namespace ns1='http://docs.openstack.org/identity/api/v2.0'; -/ns1:tenant/@enabled = "true" and /ns1:tenant/@id="my_new_tenant" and /ns1:tenant/ns1:description = "This is a description of my tenant. Thank you very much."truefalsefalse<xml-fragment/>http://localhost:8080<v1:tenant enabled="true" id="my_new_tenant" xmlns:v1="http://docs.openstack.org/identity/api/v2.0"><v1:description>This is a description of my tenant. Thank you very much.</v1:description></v1:tenant>tenantConflictfalsefalse409falsefalse<xml-fragment/>http://localhost:8080<v1:tenant enabled="false" id="mt2" xmlns:v1="http://docs.openstack.org/identity/api/v2.0"><v1:description>New Disabled Tenant</v1:description></v1:tenant>declare namespace ns1='http://docs.openstack.org/identity/api/v2.0'; -/ns1:tenant/@enabled = "false" and /ns1:tenant/@id="mt2" and /ns1:tenant/ns1:description = "New Disabled Tenant"truefalsefalse<xml-fragment/>http://localhost:8080<v1:tenant id="mt3" xmlns:v1="http://docs.openstack.org/identity/api/v2.0"><v1:description>New Tenant 3</v1:description></v1:tenant>declare namespace ns1='http://docs.openstack.org/identity/api/v2.0'; -/ns1:tenant/@id="mt3" and /ns1:tenant/ns1:description = "New Tenant 3"truefalsefalse<xml-fragment/>http://localhost:8080<v1:tenant enabled="true" xmlns:v1="http://docs.openstack.org/identity/api/v2.0"><v1:description>New Tenant No ID</v1:description></v1:tenant>400falsefalsebadRequestfalsefalse<xml-fragment/>http://localhost:8080<v1:tenant enabled="true" id="my_new_tenant" xmlns:v1="http://docs.openstack.org/identity/api/v2.0"></v1:tenant>400falsefalsebadRequestfalsefalse<xml-fragment/>http://localhost:8080{"tenant": - { - "id": "JGroup", - "description": "A description ...", - "enabled": true - } -} -declare namespace ns1='http://localhost/v1.0/tenants'; -ns1:Response/ns1:tenant/ns1:id="JGroup" and ns1:Response/ns1:tenant/ns1:enabled="true" and ns1:Response/ns1:tenant/ns1:description="A description ..."truefalsefalse<xml-fragment/>http://localhost:8080{"tenant": - { - "id": "JGroup", - "description": "A description ...", - "enabled": true - } -}tenantConflictfalsefalse409falsefalse<xml-fragment/>http://localhost:8080{"tenant": - { - "id": "JGroup33", - "description": "A description...", - "enabled": false - } -}declare namespace ns1='http://localhost/v1.0/tenants'; -ns1:Response/ns1:tenant/ns1:id = "JGroup33" and ns1:Response/ns1:tenant/ns1:enabled="false" and ns1:Response/ns1:tenant/ns1:description="A description..."truefalsefalse<xml-fragment/>http://localhost:8080{"tenant": - { - "id": "JGroup65", - "description": "A description..." - } -}declare namespace ns1='http://localhost/v1.0/tenants'; -ns1:Response/ns1:tenant/ns1:id = "JGroup65" and ns1:Response/ns1:tenant/ns1:description = "A description..."truefalsefalse<xml-fragment/>http://localhost:8080{"tenant": - { - "description": "A description...", - "enabled" : true - } -}400falsefalsebadRequestfalsefalse<xml-fragment/>http://localhost:8080{"tenant": - { - "id": "JGroup95", - "enabled": true - } -}400falsefalsebadRequestfalsefalse<xml-fragment/>http://localhost:8080{"tenant": - { - "id": "JGroup95", - "description" : "A description...", - "enabled": "true" - } -}400falsefalsebadRequestfalsefalse<xml-fragment/>http://localhost:8080declare namespace ns1='http://docs.openstack.org/identity/api/v2.0'; -count(//ns1:tenant)8falsefalse<xml-fragment/>http://localhost:8080declare namespace ns1='http://localhost/v1.0/tenants'; -count(//ns1:e)8falsefalse<xml-fragment/>http://localhost:8080declare namespace ns1='http://docs.openstack.org/identity/api/v2.0'; -ns1:tenant/@id1234falsefalsedeclare namespace ns1='http://docs.openstack.org/identity/api/v2.0'; -/ns1:tenant/@enabled and /ns1:tenant/ns1:descriptiontruefalsefalse - - -<xml-fragment/>http://localhost:8080declare namespace ns1='http://localhost/v1.0/tenants/1234'; -ns1:Response/ns1:tenant/ns1:id1234falsefalsedeclare namespace ns1='http://localhost/v1.0/tenants/1234'; -/ns1:Response/ns1:tenant/ns1:enabled and /ns1:Response/ns1:tenant/ns1:descriptiontruefalsefalse - - -<xml-fragment/>http://localhost:8080404falsefalseitemNotFoundfalsefalse - - -<xml-fragment/>http://localhost:8080<v1:tenant enabled="true" id="to_delete" - xmlns:v1="http://docs.openstack.org/identity/api/v2.0"> - <v1:description>To Be Deleted</v1:description> -</v1:tenant>declare namespace ns1='http://docs.openstack.org/identity/api/v2.0'; -/ns1:tenant/@enabled = "true" and /ns1:tenant/@id="to_delete" and /ns1:tenant/ns1:description = "To Be Deleted"truefalsefalse<xml-fragment/>http://localhost:8080declare namespace ns1='http://docs.openstack.org/identity/api/v2.0'; -ns1:tenant/@idto_deletefalsefalsedeclare namespace ns1='http://docs.openstack.org/identity/api/v2.0'; -/ns1:tenant/@enabled and /ns1:tenant/ns1:descriptiontruefalsefalse - - -<entry key="Accept" value="application/xml" xmlns="http://eviware.com/soapui/config"/>http://localhost:8080assert(context.response == null) - - -<xml-fragment/>http://localhost:8080404falsefalseitemNotFoundfalsefalse - - -<entry key="Accept" value="application/xml" xmlns="http://eviware.com/soapui/config"/>http://localhost:8080forbiddenfalsefalse403falsefalse - - -<entry key="Accept" value="application/xml" xmlns="http://eviware.com/soapui/config"/>http://localhost:8080forbiddenfalsefalse403falsefalse - - -<xml-fragment/>http://localhost:8080<v1:tenant enabled="true" id="to_update" xmlns:v1="http://docs.openstack.org/identity/api/v2.0"> - <v1:description>ToUpdate</v1:description> -</v1:tenant>declare namespace ns1='http://docs.openstack.org/identity/api/v2.0'; -/ns1:tenant/@enabled = "true" and /ns1:tenant/@id="to_update" and /ns1:tenant/ns1:description = "ToUpdate"truefalsefalse<xml-fragment/>http://localhost:8080declare namespace ns1='http://docs.openstack.org/identity/api/v2.0'; -/ns1:tenant/@id="to_update" and /ns1:tenant/@enabled = "true" and /ns1:tenant/@id="to_update" and /ns1:tenant/ns1:description = "ToUpdate"truefalsefalse - - -<xml-fragment/>http://localhost:8080<v1:tenant enabled="true" xmlns:v1="http://docs.openstack.org/identity/api/v2.0"> - <v1:description>ToUpdate2</v1:description> -</v1:tenant>declare namespace ns1='http://docs.openstack.org/identity/api/v2.0'; -/ns1:tenant/@id="to_update" and /ns1:tenant/@enabled = "true" and /ns1:tenant/ns1:description = "ToUpdate2"truefalsefalse - - -<xml-fragment/>http://localhost:8080declare namespace ns1='http://docs.openstack.org/identity/api/v2.0'; -/ns1:tenant/@id="to_update" and /ns1:tenant/@enabled = "true" and /ns1:tenant/@id="to_update" and /ns1:tenant/ns1:description = "ToUpdate2"truefalsefalse - - -<xml-fragment/>http://localhost:8080<v1:tenant enabled="false" xmlns:v1="http://docs.openstack.org/identity/api/v2.0"> - <v1:description>ToUpdate2</v1:description> -</v1:tenant>declare namespace ns1='http://docs.openstack.org/identity/api/v2.0'; -/ns1:tenant/@id="to_update" and /ns1:tenant/@enabled = "false" and /ns1:tenant/ns1:description = "ToUpdate2"truefalsefalse - - -<xml-fragment/>http://localhost:8080declare namespace ns1='http://docs.openstack.org/identity/api/v2.0'; -/ns1:tenant/@id="to_update" and /ns1:tenant/@enabled = "false" and /ns1:tenant/@id="to_update" and /ns1:tenant/ns1:description = "ToUpdate2"truefalsefalse - - -<xml-fragment/>http://localhost:8080<v1:tenant id="boogabooga" enabled="false" xmlns:v1="http://docs.openstack.org/identity/api/v2.0"> - <v1:description>ToUpdate2</v1:description> -</v1:tenant>declare namespace ns1='http://docs.openstack.org/identity/api/v2.0'; -/ns1:tenant/@id="to_update" and /ns1:tenant/@enabled = "false" and /ns1:tenant/ns1:description = "ToUpdate2"truefalsefalse - - -<xml-fragment/>http://localhost:8080declare namespace ns1='http://docs.openstack.org/identity/api/v2.0'; -/ns1:tenant/@id="to_update" and /ns1:tenant/@enabled = "false" and /ns1:tenant/@id="to_update" and /ns1:tenant/ns1:description = "ToUpdate2"truefalsefalse - - -<xml-fragment/>http://localhost:8080<v1:tenant enabled="true" xmlns:v1="http://docs.openstack.org/identity/api/v2.0"> - <v1:description>ToUpdate3</v1:description> -</v1:tenant>declare namespace ns1='http://docs.openstack.org/identity/api/v2.0'; -/ns1:tenant/@id="to_update" and /ns1:tenant/@enabled = "true" and /ns1:tenant/ns1:description = "ToUpdate3"truefalsefalse - - -<xml-fragment/>http://localhost:8080declare namespace ns1='http://docs.openstack.org/identity/api/v2.0'; -/ns1:tenant/@id="to_update" and /ns1:tenant/@enabled = "true" and /ns1:tenant/@id="to_update" and /ns1:tenant/ns1:description = "ToUpdate3"truefalsefalse - - -<entry key="Accept" value="application/xml" xmlns="http://eviware.com/soapui/config"/>http://localhost:8080assert(context.response == null) - - -<xml-fragment/>http://localhost:8080declare namespace ns1='http://docs.openstack.org/common/api/v1.0'; -count(/ns1:extensions)1falsefalse<xml-fragment/>http://localhost:8080declare namespace ns1='http://localhost/v1.0/extensions'; -count(//ns1:extensions)1falsefalse<xml-fragment/>http://localhost:8080404falsefalseitemNotFoundfalsefalse<xml-fragment/>http://localhost:8080404falsefalseitemNotFoundfalsefalse<xml-fragment/>http://localhost:8080declare namespace ns1='http://docs.openstack.org/common/api/v1.0'; -count(//ns1:version)1falsefalse<xml-fragment/>http://localhost:8080declare namespace ns1='http://localhost/v1.0'; -count(//ns1:version)1falsefalse
\ No newline at end of file diff --git a/test/__init__.py b/test/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/test/functional/base.py b/test/functional/base.py deleted file mode 100644 index d30134bc..00000000 --- a/test/functional/base.py +++ /dev/null @@ -1,77 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright (c) 2011 OpenStack, LLC. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -import dtest - -import ksapi - - -options = None - - -def _get_ksapi(): - """Get an instance of KeystoneAPI20.""" - - # If debug mode has been enabled, let's select a debug stream - dbstream = None - if options.debug: - dbstream = dtest.status - - # Build and return the API object - return ksapi.KeystoneAPI20(options.keystone, dbstream) - - -class BaseKeystoneTest(dtest.DTestCase): - """Base class for Keystone tests.""" - - def setUp(self): - """Initialize tests by setting up a KeystoneAPI20 to call.""" - - # Build the API object - self.ks = _get_ksapi() - - -class KeystoneTest(BaseKeystoneTest): - """Base class for Keystone tests.""" - - token = None - - @classmethod - def setUpClass(cls): - """Initialize tests by setting up a keystone token.""" - - # Get an API object - ks = _get_ksapi() - - # Next, let's authenticate - resp = ks.authenticate(options.username, options.password) - - # Finally, save the authentication token - cls.token = resp.obj['auth']['token']['id'] - - @classmethod - def tearDownClass(cls): - """Revoke the authentication token.""" - - # Get an API object - ks = _get_ksapi() - - # Now, let's revoke the token - resp = ks.revoke_token(cls.token, cls.token) - - # For completeness sake... - cls.token = None diff --git a/test/functional/ksapi.py b/test/functional/ksapi.py deleted file mode 100644 index 9c426109..00000000 --- a/test/functional/ksapi.py +++ /dev/null @@ -1,146 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright (c) 2011 OpenStack, LLC. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -import simplerest - - -class KeystoneAPI20(simplerest.RESTAPI): - get_version_info = simplerest.RESTMethod('get_version_info', 'GET', '/') - - get_extensions = simplerest.RESTMethod('get_extensions', 'GET', - '/extensions') - get_extension = simplerest.RESTMethod('get_extension', 'GET', - '/extensions/{alias}', ['alias']) - - authenticate = simplerest.RESTMethod('authenticate', 'POST', - '/tokens', - ['username', 'password', 'tenantId'], - 'passwordCredentials', - username='req', password='req', - tenantId=('req', False)) - validate_token = simplerest.RESTMethod('validate_token', 'GET', - '/tokens/{tokenId}', - ['x_auth_token', - 'tokenId', 'belongsTo'], - x_auth_token='header', - belongsTo='query') - revoke_token = simplerest.RESTMethod('revoke_token', 'DELETE', - '/tokens/{tokenId}', - ['x_auth_token', 'tokenId'], - x_auth_token='header') - - create_tenant = simplerest.RESTMethod('create_tenant', 'POST', '/tenants', - ['x_auth_token', 'id', - 'description', 'enabled'], - 'tenant', - x_auth_token='header', - id='req', description='req', - enabled='req') - get_tenants = simplerest.RESTMethod('get_tenants', 'GET', '/tenants', - ['x_auth_token'], - x_auth_token='header') - get_tenant = simplerest.RESTMethod('get_tenant', 'GET', - '/tenants/{tenantId}', - ['x_auth_token', 'tenantId'], - x_auth_token='header') - update_tenant = simplerest.RESTMethod('update_tenant', 'PUT', - '/tenants/{tenantId}', - ['x_auth_token', 'tenantId', - 'description'], - 'tenant', - x_auth_token='header', - description='req') - delete_tenant = simplerest.RESTMethod('delete_tenant', 'DELETE', - '/tenants/{tenantId}', - ['x_auth_token', 'tenantId'], - x_auth_token='header') - - get_base_urls = simplerest.RESTMethod('get_base_urls', 'GET', - '/baseURLs', - ['x_auth_token', 'serviceName'], - x_auth_token='header', - serviceName='query') - get_enabled_base_urls = simplerest.RESTMethod('get_enabled_base_urls', - 'GET', '/baseURLs/enabled', - ['x_auth_token', - 'serviceName'], - x_auth_token='header', - serviceName='query') - get_base_url = simplerest.RESTMethod('get_base_url', 'GET', - '/baseURLs/{baseURLId}', - ['x_auth_token', 'baseURLId'], - x_auth_token='header') - get_base_url_refs = simplerest.RESTMethod('get_base_url_refs', 'GET', - '/tenants/{tenantId}/' - 'baseURLRefs', - ['x_auth_token', 'tenantId'], - x_auth_token='header') - add_base_url_ref = simplerest.RESTMethod('add_base_url_ref', 'POST', - '/tenants/{tenantId}/' - 'baseURLRefs', - ['x_auth_token', - 'tenantId', 'id', 'region', - 'default', 'serviceName', - 'publicURL', 'internalURL', - 'enabled'], 'baseURL', - x_auth_token='header', - id='req', region='req', - default='req', - serviceName='req', - publicURL='req', - internalURL='req', enabled='req') - get_base_url_ref = simplerest.RESTMethod('get_base_url_ref', 'GET', - '/tenants/{tenantId}/' - 'baseURLRefs/{baseURLId}', - ['x_auth_token', 'tenantId', - 'baseURLId'], - x_auth_token='header') - delete_base_url_ref = simplerest.RESTMethod('delete_base_url_ref', - 'DELETE', - '/tenants/{tenantId}/' - 'baseURLRefs/{baseURLId}', - ['x_auth_token', 'tenantId', - 'baseURLId'], - x_auth_token='header') - - get_roles = simplerest.RESTMethod('get_roles', 'GET', '/roles', - ['x_auth_token', 'serviceName'], - x_auth_token='header', - serviceName='query') - get_role = simplerest.RESTMethod('get_role', 'GET', '/roles/{roleId}', - ['x_auth_token', 'roleId'], - x_auth_token='header') - get_role_refs = simplerest.RESTMethod('get_role_refs', 'GET', - '/users/{userId}/roleRefs', - ['x_auth_token', 'userId'], - x_auth_token='header') - add_role_ref = simplerest.RESTMethod('add_role_ref', 'POST', - '/users/{userId}/roleRefs', - ['x_auth_token', 'userId', 'id', - 'href', 'tenantId'], - 'roleRef', x_auth_token='header', - id='req', href='req', tenantId='req') - get_role_ref = simplerest.RESTMethod('get_role_ref', 'GET', - '/users/{userId}/roleRefs/{roleId}', - ['x_auth_token', 'userId', 'roleId'], - x_auth_token='header') - delete_role_ref = simplerest.RESTMethod('delete_role_ref', 'DELETE', - '/users/{userId}/roleRefs/' - '{roleId}', - ['x_auth_token', 'userId', - 'roleId'], - x_auth_token='header') diff --git a/test/functional/run_tests.py b/test/functional/run_tests.py deleted file mode 100755 index 944ddcc1..00000000 --- a/test/functional/run_tests.py +++ /dev/null @@ -1,63 +0,0 @@ -#!/usr/bin/python -# vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright (c) 2011 OpenStack, LLC. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -try: - import dtest -except: - print "DTest framework needed. Try running 'pip install dtest'" - exit() - -import sys - -import base - - -def add_opts(opts): - """Adds options specific to this test suite.""" - - opts.add_option("-u", "--username", - action="store", type="string", dest="username", - help="The username to use to access Keystone.") - opts.add_option("-p", "--password", - action="store", type="string", dest="password", - help="The password to use to access Keystone.") - opts.add_option("-k", "--keystone", - action="store", type="string", dest="keystone", - help="The URL to use to access Keystone.") - - return opts - - -if __name__ == '__main__': - # Obtain the options - opts = add_opts(dtest.optparser(usage="%prog [options]")) - - # Process command-line arguments, saving them so tests can get to - # them - (base.options, args) = opts.parse_args() - - # Ensure required options are present - if (not base.options.username or not base.options.password or - not base.options.keystone): - print >>sys.stderr, "Missing required options" - print >>sys.stderr, ("At a minimum, --username, --password, and " - "--keystone must be specified.") - opts.print_help(sys.stderr) - sys.exit(1) - - # Execute the test suite - sys.exit(dtest.main(**dtest.opts_to_args(base.options))) diff --git a/test/functional/sample_test.py b/test/functional/sample_test.py deleted file mode 100644 index 10d24abe..00000000 --- a/test/functional/sample_test.py +++ /dev/null @@ -1,85 +0,0 @@ -## Lines beginning with '##' are for explaining the contents of this -## file, and should be removed if you copy the file to create a new -## (set of) tests. Also note that the file must be named to match the -## scheme "test_[...].py", i.e., "test_tokens.py". -## -## I don't think I need to explain the copyright notice :) -## -# vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright (c) 2011 OpenStack, LLC. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -## This test suite uses the DTest framework, which can be found on -## PyPi ("pip install dtest"). DTest uses threading to perform tests -## in parallel; the threading can be limited by using dependencies, -## but the purpose of dependencies is really to say that some test -## must pass before other actions can be performed. Within dtest, the -## util module contains a number of useful "assert_*()" functions, but -## if you want, you can just use the "assert" statement. -## -## Also note that names are important. Modules should be named -## "test_[...].py", as mentioned above. Classes must extend -## base.KeystoneTest (a subclass of dtest.DTestCase), and test methods -## should have names like "test_[...]" (or be decorated with the -## @dtest.istest decorator). Adhere to these rules, and DTest can -## discover and run the tests without you having to do anything other -## than create them. -import dtest -from dtest import util - -## The "base" module contains KeystoneTest, which ensures that there's -## a Keystone authentication token in self.token and an API accessor -## in self.ks. See ksapi.py for a list of what methods are available -## on self.ks. -import base - - -## Tests should be gathered together in classes, not too dissimilar -## from how unittest works. Extend base.KeystoneTest, so you get -## self.token and self.ks. If you override setUp(), make sure you -## call the superclass's setUp() method (it's responsible for setting -## self.ks). Try to avoid overriding setUpClass() or tearDownClass() -## if you can help it (they're responsible for setting up and -## destroying self.token). -class SampleTest(base.KeystoneTest): - def test_sample(self): - """Test that we can do sample.""" - ## You don't *have* to declare a doc string, but it's good - ## practice. - - ## Here we're making a "sample_call()", passing self.token as - ## the authentication token. For available calls and the - ## order of arguments, check out ksapi.py. The return value - ## will be an httplib.HTTPResponse object with additional - ## 'body' (str) and 'obj' (dict) attributes. If a status code - ## greater than or equal to 400 is returned from the other - ## end, an exception will be raised; the response will be - ## attached to the 'response' attribute of the exception, and - ## the status will be on the 'status' attribute of the - ## exception. Note that redirects are followed. - resp = self.ks.sample_call(self.token, 'argument 1', 'argument 2') - - # Verify that resp is correct - util.assert_equal(resp.status, 200) - util.assert_in('sample', resp.obj) - ## Place your various assertions about the response here. - - ## Rinse, lather, repeat. You should perform only a single - ## test per test method, but if you're doing creation tests, - ## it makes sense to include the deletion test in the same - ## test method. Remember, the only control you have over test - ## ordering is by setting up dependencies (@dtest.depends()). - ## No return value is necessary. diff --git a/test/functional/simplerest.py b/test/functional/simplerest.py deleted file mode 100644 index 8455ece3..00000000 --- a/test/functional/simplerest.py +++ /dev/null @@ -1,641 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright (c) 2011 OpenStack, LLC. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -import httplib -import json -import re -import string -import urllib -import urlparse - - -class HTTPRequest(object): - """Represent an HTTP request. - - Represents an HTTP request. Headers can be manipulated using - standard dictionary access (i.e., req["accept"] will be the - contents of the "Accept" header), and the body can be fed in using - write(). Note that headers are manipulated in a case-insensitive - fashion; that is, the "accept" header is the same thing as the - "ACCEPT" header or the "aCcEpT" header. - - """ - - def __init__(self, method, uri, body=None, headers=None): - """Initialize an HTTP request. - - :param method: The HTTP method, i.e., "GET". - :param uri: The full path of the resource. - :param body: A string giving the body of the request. - :param headers: A dictionary of headers. - """ - - # Save the relevant data - self.method = method.upper() - self.uri = uri - self.body = body or '' - self.headers = {} - - # Set the headers... - if headers: - for hdr, value in headers.items(): - # Allows appropriate case mapping - self[hdr] = value - - def write(self, data): - """Write data to the request body. - - :param data: Data to be appended to the request body. - """ - - # Add the written data to our body - self.body += data - - def flush(self): - """Flush data to the request body. - - Does nothing. Provided just in case something tries to call - flush(). - """ - - # Do-nothing to allow stream compatibility - pass - - def __getitem__(self, item): - """Allow access to headers.""" - - # Headers are done by item access - return self.headers[item.title()] - - def __setitem__(self, item, value): - """Allow access to headers.""" - - # Headers are done by item access - self.headers[item.title()] = value - - def __delitem__(self, item): - """Allow access to headers.""" - - # Headers are done by item access - del self.headers[item.title()] - - def __contains__(self, item): - """Allow access to headers.""" - - # Headers are done by item access - return item.title() in self.headers - - def __len__(self): - """Allow access to headers.""" - - # Headers are done by item access - return len(self.headers) - - -class RESTClient(object): - """Represent a REST client connection. - - Represents a REST client connection. All calls will be made - relative to the base URL defined when the class is instantiated. - Note that 301, 302, 303, and 307 redirects are honored. By - default, redirects are limited to a maximum of 10; this may be - modified by setting the max_redirects class attribute. - - """ - - # Maximum number of redirects we'll follow - max_redirects = 10 - - def __init__(self, baseurl, debug_stream=None): - """Initialize a REST client. - - :param baseurl: The base URL for the client connection. - :param debug_stream: An optional stream for receiving debug. - """ - - # Save the base URL and debug stream - self._baseurl = baseurl - self._debug_stream = debug_stream - - # Pull it apart, also... - parsed = urlparse.urlparse(baseurl) - - # Make sure the scheme makes sense - if parsed.scheme not in ('http', 'https'): - raise httplib.InvalidURL("invalid scheme: '%s'" % parsed.scheme) - - # We're only concerned with the scheme, netloc, and path... - self._scheme = parsed.scheme - self._netloc = parsed.netloc - self._path = parsed.path or '/' - - # We'll keep a cached HTTPConnection for our baseurl around... - self._connect = None - - @classmethod - def _open(cls, scheme, netloc, cache=None): - """Open an HTTPConnection. - - Opens an HTTPConnection or returns an open one from the cache, - if given. If the scheme is "https", returns an - HTTPSConnection. - - :param scheme: The URI scheme; one of 'http' or 'https'. - :param netloc: The network location. - :param cache: Optional dictionary caching connections. - """ - - # If cache is present, look up the scheme and netloc in it... - if cache and (scheme, netloc) in cache: - # Return the pre-existing connection - return cache[(scheme, netloc)] - - # Open a connection for the given scheme and netloc - if scheme == 'http': - connect = httplib.HTTPConnection(netloc) - elif scheme == 'https': - connect = httplib.HTTPSConnection(netloc) - - # Make sure to cache it... - if cache is not None: - cache[(scheme, netloc)] = connect - - return connect - - def _debug(self, msg, *args, **kwargs): - """Generate debugging output.""" - - # If we have a declared debug stream, output to it - if self._debug_stream: - print >>self._debug_stream, msg % (kwargs if kwargs else args) - - def make_req(self, method, reluri, query=None, obj=None, headers=None): - """Makes an HTTPRequest. - - Generates an instance of HTTPRequest and returns it. - - :param method: The HTTP method, i.e., "GET". - :param reluri: The resource URI, relative to the base URL. - :param query: Optional dictionary to convert into a query. - :param obj: Optional object to serialize as a JSON object. - :param headers: Optional dictionary of headers. - """ - - # First, let's compose the path with the reluri - joincond = (self._path[-1:], reluri[:1]) - if joincond == ('/', '/'): - fulluri = self._path + reluri[1:] - elif '/' in joincond: - fulluri = self._path + reluri - else: - fulluri = self._path + '/' + reluri - - # Add the query, if there is one - if query: - fulluri += '?%s' % urllib.urlencode(query) - - self._debug("Creating %s request for %s", method, fulluri) - - # Set up a default for the accept header - if headers is None: - headers = {} - headers.setdefault('accept', 'application/json') - - # Build a request - req = HTTPRequest(method, fulluri, headers=headers) - - # If there's an object, jsonify it - if obj is not None: - json.dump(obj, req) - req['content-type'] = 'application/json' - self._debug(" Request body: %r" % req.body) - - # Now, return the request - return req - - def send(self, req): - """Send request. - - Sends a request, which must have been generated using - make_req() (assumes URL is relative to the base URL). Honors - redirects (even to URLs not relative to base URL). If the - status code of the response is >= 400, raises an appropriate - exception derived from HTTPException (of this module). - Returns an HTTPResponse (defined by httplib). If a JSON - object is available in the body, the obj attribute of the - response will be set to it; otherwise, obj is None. - """ - - self._debug("Sending request on client %s: (%r, %r, %r, %r)", - self._baseurl, req.method, req.uri, req.body, req.headers) - - # First, get a connection - if self._connect is None: - self._connect = self._open(self._scheme, self._netloc) - - # Pre-initialize the cache... - cache = {(self._scheme, self._netloc): self._connect} - - # Get the initial connection we'll be using... - connect = self._connect - - # Also get the initial URI we're using... - uri = req.uri - - # Need the full URL, with e.g., netloc - fullurl = urlparse.urlunparse((self._scheme, self._netloc, uri, - None, None, None)) - - # Loop for redirection handling - seen = set([fullurl]) - for i in range(self.max_redirects): - # Make the request - self._debug(" Issuing request to %s (%s)", fullurl, uri) - connect.request(req.method, uri, req.body, req.headers) - - # Get the response - resp = connect.getresponse() - - # Now, is the response a redirection? - newurl = None - if resp.status in (301, 302, 303, 307): - # Find the forwarding header... - if 'location' in resp.msg: - newurl = resp.getheader('location') - elif 'uri' in resp.msg: - newurl = resp.getheader('uri') - - # If we have a newurl, process the redirection - if newurl is not None: - # Canonicalize it; it could be relative - fullurl = urlparse.urljoin(fullurl, newurl) - - self._debug(" Got redirected to %s" % fullurl) - - # Make sure we haven't seen it before... - if fullurl in seen: - self._debug(" Redirected URL already seen!") - break - - seen.add(fullurl) - - # Now, split it back up - tmp = urlparse.urlparse(newurl) - - # Get the path part of the URL - uri = urlparse.urlunparse((None, None, tmp.path, tmp.params, - tmp.query, tmp.fragment)) - - # Finally, get a connection - connect = self._open(tmp.scheme, tmp.netloc, cache) - - # And we try again - continue - - # We have a response and it's not a redirection; let's - # interpret the JSON in the response (safely)... - self._debug(" Received %s response (%s)", resp.status, - resp.reason) - resp.body = resp.read() - try: - resp.obj = json.loads(resp.body) - self._debug(" Received entity: %r", resp.obj) - except ValueError: - resp.obj = None - self._debug(" No received entity; body %r", resp.body) - - # If this is an error response, let's raise an appropriate - # exception - if resp.status >= 400: - exc = exceptions.get(resp.status, HTTPException) - self._debug(" Response was a fault, raising %s", - exc.__name__) - raise exc(resp) - - # Return the response - return resp - - # Exceeded the maximum number of redirects - self._debug(" Redirect loop detected") - raise RESTException("Redirect loop detected") - - def get(self, reluri, query=None, headers=None): - """Send a GET request. - - :param reluri: The resource URI, relative to the base URL. - :param query: Optional dictionary to convert into a query. - :param headers: Optional dictionary of headers. - """ - - # Make a GET request... - req = self.make_req('GET', reluri, query=query, headers=headers) - - # And issue it - return self.send(req) - - def put(self, reluri, query=None, obj=None, headers=None): - """Send a PUT request. - - :param reluri: The resource URI, relative to the base URL. - :param query: Optional dictionary to convert into a query. - :param obj: Optional object to serialize as a JSON object. - :param headers: Optional dictionary of headers. - """ - - # Make a PUT request... - req = self.make_req('PUT', reluri, query=query, obj=obj, - headers=headers) - - # And issue it - return self.send(req) - - def post(self, reluri, query=None, obj=None, headers=None): - """Send a POST request. - - :param reluri: The resource URI, relative to the base URL. - :param query: Optional dictionary to convert into a query. - :param obj: Optional object to serialize as a JSON object. - :param headers: Optional dictionary of headers. - """ - - # Make a POST request... - req = self.make_req('POST', reluri, query=query, obj=obj, - headers=headers) - - # And issue it - return self.send(req) - - def delete(self, reluri, query=None, headers=None): - """Send a DELETE request. - - :param reluri: The resource URI, relative to the base URL. - :param query: Optional dictionary to convert into a query. - :param headers: Optional dictionary of headers. - """ - - # Make a DELETE request... - req = self.make_req('DELETE', reluri, query=query, headers=headers) - - # And issue it - return self.send(req) - - -class RESTException(Exception): - """Superclass for exceptions from this module.""" - - pass - - -class HTTPException(RESTException): - """Superclass of exceptions raised if an error status is returned.""" - - def __init__(self, response): - """Initializes exception, attaching response.""" - - # Formulate a message from the response - msg = response.reason - - # Initialize superclass - super(RESTException, self).__init__(msg) - - # Also attach status code and the response - self.status = response.status - self.response = response - - -# Set up more specific exceptions -exceptions = {} -for _status, _name in httplib.responses.items(): - # Skip non-error codes - if _status < 400: - continue - - # Make a valid name - _exname = re.sub(r'\W+', '', _name) + 'Exception' - - # Make a class - _cls = type(_exname, (HTTPException,), {'__doc__': _name}) - - # Now, put it in the right places - vars()[_name] = _cls - exceptions[_status] = _cls - - -class RESTMethod(object): - """Represent a REST method. - - Represents a class method which should be translated into a - request to a REST server. - - """ - - def __init__(self, name, method, uri, argorder=None, reqwrapper=None, - **kwargs): - """Initialize a REST method. - - Creates a method that will use the defined HTTP method to - access the defined resource. Extra keyword arguments specify - the names and dispositions of arguments not derived from the - uri format string. The values of those extra arguments may be - 'query', 'req', or 'header', to indicate that the argument - goes in the query string, the request object, or the request - headers. (Note that header names have '_' mapped to '-' for - convenience.) If a value is a tuple, the first element of the - tuple must be the type ('query', 'req', or 'header'), and the - second element must be either True or False, to indicate that - the argument is required. By default, all query arguments are - optional, and all other arguments are required. - - :param name: The method name. - :param method: The corresponding HTTP method. - :param uri: A relative URI for the resource. A format string. - :param reqwrapper: Key for the wrapping dictionary of the request. - :param argorder: Order arguments may be specified in. - """ - - # Save our name and method - self.name = name - self.method = method.upper() - - # Need to save the various construction information - self.uri = uri - self.reqwrapper = reqwrapper - self.argorder = argorder or [] - - # Need to determine what keys are required and where they - # go... - self.kwargs = {} - - # Start by parsing the uri format string - for text, field, fmt, conv in string.Formatter().parse(uri): - # Add field as a required kw argument - if field is not None: - self.kwargs[field] = ('uri', True) - - # Now consider other mentioned arguments... - for field, type_ in kwargs.items(): - # Don't allow duplicate fields - if field in self.kwargs: - raise RESTException("Field %r of %s() already defined as %r" % - (field, name, self.kwargs[field][0])) - - # If type_ is a tuple, first element is type and second is - # required or not - required = None - if isinstance(type_, (tuple, list)): - required = type_[1] - type_ = type_[0] - - # Ensure valid type... - if (type_ not in ('query', 'req', 'header') or - (type_ == 'req' and reqwrapper is None)): - raise RESTException("Invalid type %r for field %r of %s()" % - (type_, field, name)) - - # For query arguments, required defaults to False - if required is None: - if type_ == 'query': - required = False - else: - required = True - - # Add the field - self.kwargs[field] = (type_, required) - - def __get__(self, obj, owner): - """Retrieve a wrapper to call this REST method.""" - - # If access via class, return ourself - if obj is None: - return self - - # OK, construct a wrapper to call the method with the - # appropriate RESTClient - def wrapper(*args, **kwargs): - # Build a dictionary from zipping together argorder and - # args - newkw = dict(zip(self.argorder, args)) - - # Make kwargs override - newkw.update(kwargs) - - return self(obj._rc, newkw) - - # Copy over the name for prettiness sake - wrapper.__name__ = self.name - wrapper.func_name = self.name - - return wrapper - - def __call__(self, rc, kwargs): - """Call this REST method. - - :param rc: A RESTClient instance. - :param kwargs: A dictionary of arguments to this REST method. - """ - - rc._debug("Called %s(%r)", self.name, kwargs) - - # We're going to build an object, a query, and headers - headers = {} - query = {} - if self.reqwrapper is None: - obj = None - reqobj = None - else: - obj = {} - reqobj = {self.reqwrapper: obj} - - # Let's walk through kwargs and make sure our required - # arguments are present - seen = set() - for field, (type_, required) in self.kwargs.items(): - # Is the field present? - if field not in kwargs: - # Is it required? - if required: - rc._debug(" Required %r argument %r missing", - type_, field) - raise RESTException("Missing required argument " - "%r of %s()" % - (field, self.name)) - - # Not required, don't worry about it - rc._debug(" Optional %r argument %r missing", - type_, field) - continue - - # Send it to the right place - if type_ == 'query': - rc._debug(" Query argument %r: %r", field, kwargs[field]) - query[field] = kwargs[field] - elif type_ == 'req': - rc._debug(" Request object argument %r: %r", field, - kwargs[field]) - obj[field] = kwargs[field] - elif type_ == 'header': - # Reformulate the name - hdr = '-'.join(field.split('_')).title() - rc._debug(" Header %r argument %r: %r", hdr, field, - kwargs[field]) - headers[hdr] = kwargs[field] - - # Keep track of arguments we've used - seen.add(field) - - # Deal with unprocessed arguments - if obj is not None: - for arg in set(kwargs.keys()) - seen: - rc._debug(" Extra request object argument %r: %r", - arg, kwargs[arg]) - obj[arg] = kwargs[arg] - - # Format the URI - uri = self.uri.format(**kwargs) - rc._debug(" Request URI: %s", uri) - - # We now have all the pieces we need; create a request... - req = rc.make_req(self.method, uri, query, reqobj, headers) - - # And send it - return rc.send(req) - - -class RESTAPI(object): - """Represent a REST API. - - A convenient superclass for defining REST APIs using this toolkit. - Methods should be defined by assigning instances of RESTMethod to - class variables. - - """ - - def __init__(self, baseurl, debug_stream=None): - """Initialize a REST API. - - Creates a RESTClient instance from the baseurl and attaches it - where RESTMethod expects to find it. - """ - - # Create and save a RESTClient for our use - self._rc = RESTClient(baseurl, debug_stream) - - @property - def rc(self): - """Retrieve the RESTClient instance.""" - - return self._rc diff --git a/test/functional/test_tokens.py b/test/functional/test_tokens.py deleted file mode 100644 index 736365d9..00000000 --- a/test/functional/test_tokens.py +++ /dev/null @@ -1,51 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright (c) 2011 OpenStack, LLC. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -import dtest -from dtest import util - -import base - - -class AuthenticateTest(base.BaseKeystoneTest): - def test_authenticate(self): - """Test that we can authenticate using Keystone.""" - - # Issue the authentication request - resp = self.ks.authenticate(base.options.username, - base.options.password) - - # Verify that resp is correct - util.assert_equal(resp.status, 200) - util.assert_in('auth', resp.obj) - util.assert_in('token', resp.obj['auth']) - util.assert_in('expires', resp.obj['auth']['token']) - util.assert_in('id', resp.obj['auth']['token']) - util.assert_in('user', resp.obj['auth']) - util.assert_in('username', resp.obj['auth']['user']) - util.assert_in('tenantId', resp.obj['auth']['user']) - util.assert_equal(resp.obj['auth']['user']['username'], - base.options.username) - - # Now ensure we can revoke an authentication token - auth_tok = resp.obj['auth']['token']['id'] - resp = self.ks.revoke_token(auth_tok, auth_tok) - util.assert_equal(resp.status, 204) - - -# Ensure that all remaining tests wait for test_authenticate -dtest.depends(AuthenticateTest.test_authenticate)(base.KeystoneTest.setUpClass) diff --git a/test/kill.sql b/test/kill.sql deleted file mode 100644 index 66e3733f..00000000 --- a/test/kill.sql +++ /dev/null @@ -1,10 +0,0 @@ --- --- Clean up the DB --- - -delete from users; -delete from tenants; -delete from groups; -delete from user_group_association; -delete from user_tenant_association; -delete from token; diff --git a/test/unit/__init__.py b/test/unit/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/test/unit/base.py b/test/unit/base.py deleted file mode 100644 index 0d59bba1..00000000 --- a/test/unit/base.py +++ /dev/null @@ -1,282 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright (c) 2011 OpenStack, LLC. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Base test case classes for the unit tests""" - -import datetime -import functools -import json -import httplib -import logging -import pprint -import unittest - -from lxml import etree, objectify -import webob - -from keystone import server -from keystone.db.sqlalchemy import api as db_api - -logger = logging.getLogger('test.unit.base') - - -class ServiceAPITest(unittest.TestCase): - - """ - Base test case class for any unit test that tests the main service API. - """ - - """ - The `api` attribute for this base class is the `server.KeystoneAPI` - controller. - """ - api_class = server.KeystoneAPI - - """ - Dict of configuration options to pass to the API controller - """ - options = {'sql_connection': 'sqlite:///', # in-memory db - 'verbose': False, - 'debug': False} - - """ - Set of dicts of tenant attributes we start each test case with - """ - tenant_fixtures = [ - {'id': 'tenant1', - 'enabled': True, - 'desc': 'tenant1'} - ] - - """ - Attributes of the user the test creates for each test case that - will authenticate against the API. The `auth_user` attribute - will contain the created user with the following attributes. - """ - auth_user_attrs = {'id': 'auth_user', - 'password': 'auth_pass', - 'email': 'auth_user@example.com', - 'enabled': True, - 'tenant_id': 'tenant1'} - """ - Special attribute that is the identifier of the token we use in - authenticating. Makes it easy to test the authentication process. - """ - auth_token_id = 'SPECIALAUTHTOKEN' - - """ - Content-type of requests. Generally, you don't need to manually - change this. Instead, :see test.unit.decorators - """ - content_type = 'json' - - """ - Version of the API to test - """ - api_version = '2.0' - - def setUp(self): - self.api = self.api_class(self.options) - - self.expires = datetime.datetime.utcnow() - self.clear_all_data() - - # Create all our base tenants - for tenant in self.tenant_fixtures: - self.fixture_create_tenant(**tenant) - - # Create the user we will authenticate with - self.auth_user = self.fixture_create_user(**self.auth_user_attrs) - self.auth_token = self.fixture_create_token( - user_id=self.auth_user['id'], - tenant_id=self.auth_user['tenant_id'], - expires=self.expires, - token_id=self.auth_token_id) - - self.add_verify_status_helpers() - - def tearDown(self): - self.clear_all_data() - setattr(self, 'req', None) - setattr(self, 'res', None) - - def clear_all_data(self): - """ - Purges the database of all data - """ - db_api.unregister_models() - logger.debug("Cleared all data from database") - db_api.register_models() - - def fixture_create_tenant(self, **kwargs): - """ - Creates a tenant fixture. - - :params **kwargs: Attributes of the tenant to create - """ - values = kwargs.copy() - tenant = db_api.tenant_create(values) - logger.debug("Created tenant fixture %s", values['id']) - return tenant - - def fixture_create_user(self, **kwargs): - """ - Creates a user fixture. If the user's tenant ID is set, and the tenant - does not exist in the database, the tenant is created. - - :params **kwargs: Attributes of the user to create - """ - values = kwargs.copy() - tenant_id = values.get('tenant_id') - if tenant_id: - if not db_api.tenant_get(tenant_id): - db_api.tenant_create({'id': tenant_id, - 'enabled': True, - 'desc': tenant_id}) - user = db_api.user_create(values) - logger.debug("Created user fixture %s", values['id']) - return user - - def fixture_create_token(self, **kwargs): - """ - Creates a token fixture. - - :params **kwargs: Attributes of the token to create - """ - values = kwargs.copy() - token = db_api.token_create(values) - logger.debug("Created token fixture %s", values['token_id']) - return token - - def get_request(self, method, url, headers=None): - """ - Sets the `req` attribute to a `webob.Request` object that - is constructed with the supplied method and url. Supplied - headers are added to appropriate Content-type headers. - """ - headers = headers or {} - self.req = webob.Request.blank('/v%s/%s' % (self.api_version, - url.lstrip('/'))) - self.req.method = method - self.req.headers = headers - if 'content-type' not in headers: - ct = 'application/%s' % self.content_type - self.req.headers['content-type'] = ct - self.req.headers['accept'] = ct - return self.req - - def get_response(self): - """ - Sets the appropriate headers for the `req` attribute for - the current content type, then calls `req.get_response()` and - sets the `res` attribute to the returned `webob.Response` object - """ - self.res = self.req.get_response(self.api) - logger.debug("%s %s returned %s", self.req.method, self.req.path_qs, - self.res.status) - if self.res.status_int != httplib.OK: - logger.debug("Response Body:") - for line in self.res.body.split("\n"): - logger.debug(line) - return self.res - - def verify_status(self, status_code): - """ - Simple convenience wrapper for validating a response's status - code. - """ - if not getattr(self, 'res'): - raise RuntimeError("Called verify_status() before calling " - "get_response()!") - - self.assertEqual(status_code, self.res.status_int, - "Incorrect status code %d. Expected %d" % - (self.res.status_int, status_code)) - - def add_verify_status_helpers(self): - """ - Adds some convenience helpers using partials... - """ - self.status_ok = functools.partial(self.verify_status, - httplib.OK) - self.status_not_found = functools.partial(self.verify_status, - httplib.NOT_FOUND) - self.status_unauthorized = functools.partial(self.verify_status, - httplib.UNAUTHORIZED) - self.status_bad_request = functools.partial(self.verify_status, - httplib.BAD_REQUEST) - - def assert_dict_equal(self, expected, got): - """ - Compares two dicts for equality and prints the dictionaries - nicely formatted for easy comparison if there is a failure. - """ - self.assertEqual(expected, got, "Mappings are not equal.\n" - "Got:\n%s\nExpected:\n%s" % - (pprint.pformat(got), - pprint.pformat(expected))) - - def assert_xml_strings_equal(self, expected, got): - """ - Compares two XML strings for equality by parsing them both - into DOMs. Prints the DOMs nicely formatted for easy comparison - if there is a failure. - """ - # This is a nice little trick... objectify.fromstring() returns - # a DOM different from etree.fromstring(). The objectify version - # removes any different whitespacing... - got = objectify.fromstring(got) - expected = objectify.fromstring(expected) - self.assertEqual(etree.tostring(expected), - etree.tostring(got), "DOMs are not equal.\n" - "Got:\n%s\nExpected:\n%s" % - (etree.tostring(got, pretty_print=True), - etree.tostring(expected, pretty_print=True))) - - -class AdminAPITest(ServiceAPITest): - - """ - Base test case class for any unit test that tests the admin API. The - """ - - """ - The `api` attribute for this base class is the `server.KeystoneAdminAPI` - controller. - """ - api_class = server.KeystoneAdminAPI - - """ - Set of dicts of tenant attributes we start each test case with - """ - tenant_fixtures = [ - {'id': 'tenant1', - 'enabled': True, - 'desc': 'tenant1'}, - {'id': 'tenant2', - 'enabled': True, - 'desc': 'tenant2'} - ] - - """ - Attributes of the user the test creates for each test case that - will authenticate against the API. - """ - auth_user_attrs = {'id': 'admin_user', - 'password': 'admin_pass', - 'email': 'admin_user@example.com', - 'enabled': True, - 'tenant_id': 'tenant2'} diff --git a/test/unit/decorators.py b/test/unit/decorators.py deleted file mode 100644 index 17a7d432..00000000 --- a/test/unit/decorators.py +++ /dev/null @@ -1,49 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright (c) 2011 OpenStack, LLC. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Decorators useful in unit tests""" - -import functools - - -def content_type(func, content_type='json'): - """ - Decorator for a test case method that sets the test case's - content_type to 'json' or 'xml' and resets it afterwards to - the original setting. This also asserts that if there is a - value for the test object's `res` attribute, that the content-type - header of the response is correct. - """ - @functools.wraps(func) - def wrapped(*a, **kwargs): - test_obj = a[0] - orig_content_type = test_obj.content_type - try: - test_obj.content_type = content_type - func(*a, **kwargs) - if getattr(test_obj, 'res'): - expected = 'application/%s' % content_type - got = test_obj.res.headers['content-type'].split(';')[0] - test_obj.assertEqual(expected, got, - "Bad content type: %s. Expected: %s" % - (got, expected)) - finally: - test_obj.content_type = orig_content_type - return wrapped - - -jsonify = functools.partial(content_type, content_type='json') -xmlify = functools.partial(content_type, content_type='xml') diff --git a/test/unit/test_BaseURLs.py b/test/unit/test_BaseURLs.py deleted file mode 100644 index fa352f93..00000000 --- a/test/unit/test_BaseURLs.py +++ /dev/null @@ -1,667 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright (c) 2010-2011 OpenStack, LLC. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -import httplib2 -import json -from lxml import etree -import os -import sys -sys.path.append(os.path.abspath(os.path.join(os.path.abspath(__file__), - '..', '..', '..', '..', 'keystone'))) -import unittest - -import test_common as utils -from test_common import URL - -class BaseURLsTest(unittest.TestCase): - def setUp(self): - self.tenant = utils.get_tenant() - self.password = utils.get_password() - self.email = utils.get_email() - self.user = utils.get_user() - self.userdisabled = utils.get_userdisabled() - self.auth_token = utils.get_auth_token() - self.exp_auth_token = utils.get_exp_auth_token() - self.disabled_token = utils.get_disabled_token() - self.missing_token = utils.get_none_token() - self.invalid_token = utils.get_non_existing_token() - utils.create_tenant(self.tenant, str(self.auth_token)) - utils.create_user(self.tenant, self.user, self.auth_token) - self.token = utils.get_token(self.user, 'secrete', self.tenant, - 'token') - - def tearDown(self): - utils.delete_user(self.tenant, self.user, self.auth_token) - utils.delete_tenant(self.tenant, self.auth_token) - utils.delete_all_baseurls_ref(self.tenant, self.auth_token) - -class GetBaseURLsTest(BaseURLsTest): - def test_get_baseURLs(self): - header = httplib2.Http(".cache") - url = '%sbaseURLs' % (utils.URL) - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body='{}', - headers={"Content-Type": "application/json", - "X-Auth-Token": self.auth_token}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(200, int(resp['status'])) - - #verify content - obj = json.loads(content) - if not "baseURLs" in obj: - raise self.fail("Expecting BaseURLs") - - def test_get_baseURLs_using_expired_auth_token(self): - header = httplib2.Http(".cache") - url = '%sbaseURLs' % (utils.URL) - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body='{}', - headers={"Content-Type": "application/json", - "X-Auth-Token": self.exp_auth_token}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(403 , int(resp['status'])) - - def test_get_baseURLs_using_disabled_auth_token(self): - header = httplib2.Http(".cache") - url = '%sbaseURLs' % (utils.URL) - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body='{}', - headers={"Content-Type": "application/json", - "X-Auth-Token": self.disabled_token}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(403 , int(resp['status'])) - - def test_get_baseURLs_using_missing_auth_token(self): - header = httplib2.Http(".cache") - url = '%sbaseURLs' % (utils.URL) - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body='{}', - headers={"Content-Type": "application/json", - "X-Auth-Token": self.missing_token}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(401 , int(resp['status'])) - - def test_get_baseURLs_using_invalid_auth_token(self): - header = httplib2.Http(".cache") - url = '%sbaseURLs' % (utils.URL) - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body='{}', - headers={"Content-Type": "application/json", - "X-Auth-Token": self.invalid_token}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(404 , int(resp['status'])) - - def test_get_baseURLs_xml(self): - header = httplib2.Http(".cache") - url = '%sbaseURLs' % (utils.URL) - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body='{}', - headers={"Content-Type": "application/xml", - "X-Auth-Token": self.auth_token, - "ACCEPT": "application/xml"}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(200, int(resp['status'])) - - #verify content - dom = etree.Element("root") - dom.append(etree.fromstring(content)) - baseURLs = dom.find("{http://docs.openstack.org/identity/api/v2.0}" \ - "baseURLs") - if baseURLs == None: - self.fail("Expecting BaseURLs") - - def test_get_baseURLs_xml_expired_auth_token(self): - header = httplib2.Http(".cache") - url = '%sbaseURLs' % (utils.URL) - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body='{}', - headers={"Content-Type": "application/xml", - "X-Auth-Token": self.exp_auth_token, - "ACCEPT": "application/xml"}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(403, int(resp['status'])) - - def test_get_baseURLs_xml_disabled_auth_token(self): - header = httplib2.Http(".cache") - url = '%sbaseURLs' % (utils.URL) - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body='{}', - headers={"Content-Type": "application/xml", - "X-Auth-Token": self.disabled_token, - "ACCEPT": "application/xml"}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(403, int(resp['status'])) - - def test_get_baseURLs_xml_missing_auth_token(self): - header = httplib2.Http(".cache") - url = '%sbaseURLs' % (utils.URL) - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body='{}', - headers={"Content-Type": "application/xml", - "X-Auth-Token": self.missing_token, - "ACCEPT": "application/xml"}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(401, int(resp['status'])) - - def test_get_baseURLs_xml_invalid_auth_token(self): - header = httplib2.Http(".cache") - url = '%sbaseURLs' % (utils.URL) - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body='{}', - headers={"Content-Type": "application/xml", - "X-Auth-Token": self.invalid_token, - "ACCEPT": "application/xml"}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(404, int(resp['status'])) - -class GetBaseURLTest(BaseURLsTest): - def test_get_baseURL(self): - header = httplib2.Http(".cache") - url = '%sbaseURLs/%s' % (utils.URL, '1') - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body='{}', - headers={"Content-Type": "application/json", - "X-Auth-Token": self.auth_token}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(200, int(resp['status'])) - - #verify content - obj = json.loads(content) - if not "baseURL" in obj: - raise self.fail("Expecting BaseURL") - - def test_get_baseURL_using_expired_auth_token(self): - header = httplib2.Http(".cache") - url = '%sbaseURLs/%s' % (utils.URL, '1') - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body='{}', - headers={"Content-Type": "application/json", - "X-Auth-Token": self.exp_auth_token}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(403, int(resp['status'])) - - def test_get_baseURL_using_disabled_auth_token(self): - header = httplib2.Http(".cache") - url = '%sbaseURLs/%s' % (utils.URL, '1') - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body='{}', - headers={"Content-Type": "application/json", - "X-Auth-Token": self.disabled_token}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(403, int(resp['status'])) - - def test_get_baseURL_using_missing_auth_token(self): - header = httplib2.Http(".cache") - url = '%sbaseURLs/%s' % (utils.URL, '1') - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body='{}', - headers={"Content-Type": "application/json", - "X-Auth-Token": self.missing_token}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(401, int(resp['status'])) - - - def test_get_baseURL_using_invalid_auth_token(self): - header = httplib2.Http(".cache") - url = '%sbaseURLs/%s' % (utils.URL, '1') - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body='{}', - headers={"Content-Type": "application/json", - "X-Auth-Token": self.invalid_token}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(404, int(resp['status'])) - - def test_get_baseURL_xml(self): - header = httplib2.Http(".cache") - url = '%sbaseURLs/%s' % (utils.URL,'1') - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body='{}', - headers={"Content-Type": "application/xml", - "X-Auth-Token": self.auth_token, - "ACCEPT": "application/xml"}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(200, int(resp['status'])) - - #verify content - dom = etree.Element("root") - dom.append(etree.fromstring(content)) - baseURL = dom.find("{http://docs.openstack.org/identity/api/v2.0}" \ - "baseURL") - if baseURL == None: - self.fail("Expecting BaseURL") - - -class CreateBaseURLRefsTest(BaseURLsTest): - def test_baseurls_ref_create_json(self): - header = httplib2.Http(".cache") - resp, content = utils.create_baseurls_ref(self.tenant,"1", - str(self.auth_token)) - resp_val = int(resp['status']) - self.assertEqual(201, resp_val) - - def test_baseurls_ref_create_json_using_expired_token(self): - header = httplib2.Http(".cache") - resp, content = utils.create_baseurls_ref(self.tenant,"1", - str(self.exp_auth_token)) - resp_val = int(resp['status']) - self.assertEqual(403, resp_val) - - def test_baseurls_ref_create_json_using_disabled_token(self): - header = httplib2.Http(".cache") - resp, content = utils.create_baseurls_ref(self.tenant,"1", - str(self.disabled_token)) - resp_val = int(resp['status']) - self.assertEqual(403, resp_val) - - def test_baseurls_ref_create_json_using_missing_token(self): - header = httplib2.Http(".cache") - resp, content = utils.create_baseurls_ref(self.tenant,"1", - str(self.missing_token)) - resp_val = int(resp['status']) - self.assertEqual(401, resp_val) - - def test_baseurls_ref_create_json_using_invalid_token(self): - header = httplib2.Http(".cache") - resp, content = utils.create_baseurls_ref(self.tenant,"1", - str(self.invalid_token)) - resp_val = int(resp['status']) - self.assertEqual(404, resp_val) - - def test_baseurls_ref_create_xml(self): - header = httplib2.Http(".cache") - - resp, content = utils.create_baseurls_ref_xml(self.tenant,"1", - str(self.auth_token)) - resp_val = int(resp['status']) - self.assertEqual(201, resp_val) - url = '%stenants/%s/baseURLRefs/%s' % (URL, self.tenant, '1') - resp, content = header.request(url, "DELETE", body='', - headers={"Content-Type": "application/json", - "X-Auth-Token": str(self.auth_token)}) - resp_val = int(resp['status']) - self.assertEqual(204, resp_val) - - def test_baseurls_ref_create_xml_using_expired_token(self): - header = httplib2.Http(".cache") - - resp, content = utils.create_baseurls_ref_xml(self.tenant,"1", - str(self.auth_token)) - resp_val = int(resp['status']) - self.assertEqual(201, resp_val) - url = '%stenants/%s/baseURLRefs/%s' % (URL, self.tenant, '1') - resp, content = header.request(url, "DELETE", body='', - headers={"Content-Type": "application/json", - "X-Auth-Token": str(self.exp_auth_token)}) - resp_val = int(resp['status']) - self.assertEqual(403, resp_val) - - def test_baseurls_ref_create_xml_using_disabled_token(self): - header = httplib2.Http(".cache") - - resp, content = utils.create_baseurls_ref_xml(self.tenant,"1", - str(self.auth_token)) - resp_val = int(resp['status']) - self.assertEqual(201, resp_val) - url = '%stenants/%s/baseURLRefs/%s' % (URL, self.tenant, '1') - resp, content = header.request(url, "DELETE", body='', - headers={"Content-Type": "application/json", - "X-Auth-Token": str(self.disabled_token)}) - resp_val = int(resp['status']) - self.assertEqual(403, resp_val) - - def test_baseurls_ref_create_xml_using_missing_token(self): - header = httplib2.Http(".cache") - - resp, content = utils.create_baseurls_ref_xml(self.tenant,"1", - str(self.auth_token)) - resp_val = int(resp['status']) - self.assertEqual(201, resp_val) - url = '%stenants/%s/baseURLRefs/%s' % (URL, self.tenant, '1') - resp, content = header.request(url, "DELETE", body='', - headers={"Content-Type": "application/json", - "X-Auth-Token": str(self.missing_token)}) - resp_val = int(resp['status']) - self.assertEqual(401, resp_val) - - def test_baseurls_ref_create_xml_using_invalid_token(self): - header = httplib2.Http(".cache") - - resp, content = utils.create_baseurls_ref_xml(self.tenant,"1", - str(self.auth_token)) - resp_val = int(resp['status']) - self.assertEqual(201, resp_val) - url = '%stenants/%s/baseURLRefs/%s' % (URL, self.tenant, '1') - resp, content = header.request(url, "DELETE", body='', - headers={"Content-Type": "application/json", - "X-Auth-Token": str(self.invalid_token)}) - resp_val = int(resp['status']) - self.assertEqual(404, resp_val) - -class GetBaseURLRefsTest(BaseURLsTest): - def test_get_baseurls_ref_xml(self): - header = httplib2.Http(".cache") - url = '%stenants/%s/baseURLRefs' % (URL, self.tenant) - #test for Content-Type = application/xml - resp, content = header.request(url, "GET", body='{}', - headers={"Content-Type": "application/xml", - "X-Auth-Token": str(self.auth_token), - "ACCEPT": "application/xml"}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(200, int(resp['status'])) - - def test_get_baseurls_ref_xml_using_expired_auth_token(self): - header = httplib2.Http(".cache") - url = '%stenants/%s/baseURLRefs' % (URL, self.tenant) - #test for Content-Type = application/xml - resp, content = header.request(url, "GET", body='{}', - headers={"Content-Type": "application/xml", - "X-Auth-Token": str(self.exp_auth_token), - "ACCEPT": "application/xml"}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(403, int(resp['status'])) - - def test_get_baseurls_ref_xml_using_disabled_auth_token(self): - header = httplib2.Http(".cache") - url = '%stenants/%s/baseURLRefs' % (URL, self.tenant) - #test for Content-Type = application/xml - resp, content = header.request(url, "GET", body='{}', - headers={"Content-Type": "application/xml", - "X-Auth-Token": str(self.disabled_token), - "ACCEPT": "application/xml"}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(403, int(resp['status'])) - - def test_get_baseurls_ref_xml_using_missing_auth_token(self): - header = httplib2.Http(".cache") - url = '%stenants/%s/baseURLRefs' % (URL, self.tenant) - #test for Content-Type = application/xml - resp, content = header.request(url, "GET", body='{}', - headers={"Content-Type": "application/xml", - "X-Auth-Token": str(self.missing_token), - "ACCEPT": "application/xml"}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(401, int(resp['status'])) - - def test_get_baseurls_ref_xml_using_invalid_auth_token(self): - header = httplib2.Http(".cache") - url = '%stenants/%s/baseURLRefs' % (URL, self.tenant) - #test for Content-Type = application/xml - resp, content = header.request(url, "GET", body='{}', - headers={"Content-Type": "application/xml", - "X-Auth-Token": str(self.invalid_token), - "ACCEPT": "application/xml"}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(404, int(resp['status'])) - - def test_get_baseurls_ref_json(self): - header = httplib2.Http(".cache") - url = '%stenants/%s/baseURLRefs' % (URL, self.tenant) - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body='{}', - headers={"Content-Type": "application/json", - "X-Auth-Token": str(self.auth_token), - "ACCEPT": "application/json"}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(200, int(resp['status'])) - obj = json.loads(content) - if not "baseURLRefs" in obj: - raise self.fail("Expecting BaseURLRefs") - - def test_get_baseurls_ref_json_using_expired_auth_token(self): - header = httplib2.Http(".cache") - url = '%stenants/%s/baseURLRefs' % (URL, self.tenant) - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body='{}', - headers={"Content-Type": "application/json", - "X-Auth-Token": str(self.exp_auth_token), - "ACCEPT": "application/json"}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(403, int(resp['status'])) - obj = json.loads(content) - - def test_get_baseurls_ref_json_using_disabled_auth_token(self): - header = httplib2.Http(".cache") - url = '%stenants/%s/baseURLRefs' % (URL, self.tenant) - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body='{}', - headers={"Content-Type": "application/json", - "X-Auth-Token": str(self.disabled_token), - "ACCEPT": "application/json"}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(403, int(resp['status'])) - obj = json.loads(content) - - def test_get_baseurls_ref_json_using_missing_auth_token(self): - header = httplib2.Http(".cache") - url = '%stenants/%s/baseURLRefs' % (URL, self.tenant) - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body='{}', - headers={"Content-Type": "application/json", - "X-Auth-Token": str(self.missing_token), - "ACCEPT": "application/json"}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(401, int(resp['status'])) - obj = json.loads(content) - - def test_get_baseurls_ref_json_using_invalid_auth_token(self): - header = httplib2.Http(".cache") - url = '%stenants/%s/baseURLRefs' % (URL, self.tenant) - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body='{}', - headers={"Content-Type": "application/json", - "X-Auth-Token": str(self.invalid_token), - "ACCEPT": "application/json"}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(404, int(resp['status'])) - obj = json.loads(content) - -class DeleteBaseURLRefsTest(BaseURLsTest): - def test_delete_baseurlref(self): - header = httplib2.Http(".cache") - resp, content = utils.create_baseurls_ref(self.tenant,"1", - str(self.auth_token)) - resp_val = int(resp['status']) - self.assertEqual(201, resp_val) - obj = json.loads(content) - if not "baseURLRef" in obj: - raise fault.BadRequestFault("Expecting baseURLRef") - base_url_ref = obj["baseURLRef"] - if not "id" in base_url_ref: - base_url_ref_id = None - else: - base_url_ref_id = base_url_ref["id"] - if base_url_ref_id is None: - raise fault.BadRequestFault("Expecting baseURLRefID") - url = '%stenants/%s/baseURLRefs/%s' % (URL, self.tenant, base_url_ref_id) - resp, content = header.request(url, "DELETE", body='', - headers={"Content-Type": "application/json", - "X-Auth-Token": str(self.auth_token)}) - resp_val = int(resp['status']) - self.assertEqual(204, resp_val) - - def test_delete_baseurlref_using_expired_auth_token(self): - header = httplib2.Http(".cache") - resp, content = utils.create_baseurls_ref(self.tenant,"1", - str(self.auth_token)) - resp_val = int(resp['status']) - self.assertEqual(201, resp_val) - obj = json.loads(content) - if not "baseURLRef" in obj: - raise fault.BadRequestFault("Expecting baseURLRef") - base_url_ref = obj["baseURLRef"] - if not "id" in base_url_ref: - base_url_ref_id = None - else: - base_url_ref_id = base_url_ref["id"] - if base_url_ref_id is None: - raise fault.BadRequestFault("Expecting baseURLRefID") - url = '%stenants/%s/baseURLRefs/%s' % (URL, self.tenant, base_url_ref_id) - resp, content = header.request(url, "DELETE", body='', - headers={"Content-Type": "application/json", - "X-Auth-Token": str(self.exp_auth_token)}) - resp_val = int(resp['status']) - self.assertEqual(403, resp_val) - - def test_delete_baseurlref_using_disabled_auth_token(self): - header = httplib2.Http(".cache") - resp, content = utils.create_baseurls_ref(self.tenant,"1", - str(self.auth_token)) - resp_val = int(resp['status']) - self.assertEqual(201, resp_val) - obj = json.loads(content) - if not "baseURLRef" in obj: - raise fault.BadRequestFault("Expecting baseURLRef") - base_url_ref = obj["baseURLRef"] - if not "id" in base_url_ref: - base_url_ref_id = None - else: - base_url_ref_id = base_url_ref["id"] - if base_url_ref_id is None: - raise fault.BadRequestFault("Expecting baseURLRefID") - url = '%stenants/%s/baseURLRefs/%s' % (URL, self.tenant, base_url_ref_id) - resp, content = header.request(url, "DELETE", body='', - headers={"Content-Type": "application/json", - "X-Auth-Token": str(self.disabled_token)}) - resp_val = int(resp['status']) - self.assertEqual(403, resp_val) - - def test_delete_baseurlref_using_missing_auth_token(self): - header = httplib2.Http(".cache") - resp, content = utils.create_baseurls_ref(self.tenant,"1", - str(self.auth_token)) - resp_val = int(resp['status']) - self.assertEqual(201, resp_val) - obj = json.loads(content) - if not "baseURLRef" in obj: - raise fault.BadRequestFault("Expecting baseURLRef") - base_url_ref = obj["baseURLRef"] - if not "id" in base_url_ref: - base_url_ref_id = None - else: - base_url_ref_id = base_url_ref["id"] - if base_url_ref_id is None: - raise fault.BadRequestFault("Expecting baseURLRefID") - url = '%stenants/%s/baseURLRefs/%s' % (URL, self.tenant, base_url_ref_id) - resp, content = header.request(url, "DELETE", body='', - headers={"Content-Type": "application/json", - "X-Auth-Token": str(self.missing_token)}) - resp_val = int(resp['status']) - self.assertEqual(401, resp_val) - - def test_delete_baseurlref_using_invalid_auth_token(self): - header = httplib2.Http(".cache") - resp, content = utils.create_baseurls_ref(self.tenant,"1", - str(self.auth_token)) - resp_val = int(resp['status']) - self.assertEqual(201, resp_val) - obj = json.loads(content) - if not "baseURLRef" in obj: - raise fault.BadRequestFault("Expecting baseURLRef") - base_url_ref = obj["baseURLRef"] - if not "id" in base_url_ref: - base_url_ref_id = None - else: - base_url_ref_id = base_url_ref["id"] - if base_url_ref_id is None: - raise fault.BadRequestFault("Expecting baseURLRefID") - url = '%stenants/%s/baseURLRefs/%s' % (URL, self.tenant, base_url_ref_id) - resp, content = header.request(url, "DELETE", body='', - headers={"Content-Type": "application/json", - "X-Auth-Token": str(self.invalid_token)}) - resp_val = int(resp['status']) - self.assertEqual(404, resp_val) - -if __name__ == '__main__': - unittest.main() \ No newline at end of file diff --git a/test/unit/test_auth.py b/test/unit/test_auth.py deleted file mode 100644 index e51cbbb6..00000000 --- a/test/unit/test_auth.py +++ /dev/null @@ -1,34 +0,0 @@ -import unittest -import os -import sys -import json - -sys.path.append(os.path.abspath(os.path.join(os.path.abspath(__file__), - '..', '..', '..', '..', 'keystone'))) - -from keystone import server -import keystone.logic.types.auth as auth -import keystone.logic.types.fault as fault - -from StringIO import StringIO -from datetime import date -from lxml import etree - - -class TestAuth(unittest.TestCase): - '''Unit tests for auth.py.''' - - pwd_xml = ' \ - ' - - def test_pwd_cred_marshall(self): - creds = auth.PasswordCredentials.from_xml(self.pwd_xml) - self.assertTrue(creds.password,"secret") - self.assertTrue(creds.username,"username") - - -if __name__ == '__main__': - unittest.main() \ No newline at end of file diff --git a/test/unit/test_authentication.py b/test/unit/test_authentication.py deleted file mode 100755 index 74089023..00000000 --- a/test/unit/test_authentication.py +++ /dev/null @@ -1,215 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright (c) 2010-2011 OpenStack, LLC. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -import httplib2 -import json -from lxml import etree -import os -import sys -# Need to access identity module -sys.path.append(os.path.abspath(os.path.join(os.path.abspath(__file__), - '..', '..', '..', '..', 'keystone'))) -import unittest -from webtest import TestApp - -import test_common as utils - - -class AuthenticationTest(unittest.TestCase): - - def setUp(self): - self.tenant = utils.get_tenant() - self.token = utils.get_token('joeuser', 'secrete', self.tenant, - 'token') - #self.user = utils.get_user() - self.userdisabled = utils.get_userdisabled() - self.auth_token = utils.get_auth_token() - utils.create_baseurls_ref(self.tenant, "1", - str(self.auth_token)) - utils.create_baseurls_ref(self.tenant, "2", - str(self.auth_token)) - utils.create_baseurls_ref(self.tenant, "3", - str(self.auth_token)) - #self.exp_auth_token = utils.get_exp_auth_token() - #self.disabled_token = utils.get_disabled_token() - - def tearDown(self): - utils.delete_all_baseurls_ref(self.tenant, self.auth_token) - utils.delete_token(self.token, self.auth_token) - - def test_a_authorize(self): - resp, content = utils.get_token('joeuser', 'secrete', self.tenant) - self.assertEqual(200, int(resp['status'])) - obj = content - if not "auth" in obj: - raise fault.BadRequestFault("Expecting Auth") - auth = obj["auth"] - if not "serviceCatalog" in auth: - raise fault.BadRequestFault("Expecting Service Catalog") - - self.assertEqual('application/json', utils.content_type(resp)) - - def test_a_authorize_xml(self): - resp, content = utils.get_token_xml('joeuser', 'secrete', - self.tenant) - self.assertEqual(200, int(resp['status'])) - self.assertEqual('application/xml', utils.content_type(resp)) - #verify content - dom = etree.Element("root") - dom.append(etree.fromstring(content)) - auth = dom.find("{http://docs.openstack.org/identity/api/v2.0}" \ - "auth") - if auth == None: - self.fail("Expecting Auth") - service_catalog = auth.find( - "{http://docs.openstack.org/identity/api/v2.0}" \ - "serviceCatalog") - if service_catalog == None: - self.fail("Expecting Service Catalog") - - def test_a_authorize_legacy(self): - resp, content = utils.get_token_legacy('joeuser', 'secrete') - self.assertEqual(204, int(resp['status'])) - self.assertTrue(resp['x-auth-token']) - self.assertTrue(resp['x-server-management-url']) - self.assertTrue(resp['x-storage-url']) - self.assertTrue(resp['x-cdn-management-url']) - - def test_a_authorize_user_disabled(self): - header = httplib2.Http(".cache") - url = '%stokens' % utils.URL - body = {"passwordCredentials": {"username": self.userdisabled, - "password": "secrete", - "tenantId": self.tenant}} - resp, content = header.request(url, "POST", body=json.dumps(body), - headers={"Content-Type": "application/json"}) - - content = json.loads(content) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(403, int(resp['status'])) - self.assertEqual('application/json', utils.content_type(resp)) - - def test_a_authorize_user_disabled_xml(self): - header = httplib2.Http(".cache") - url = '%stokens' % utils.URL - body = ' \ - ' % (self.userdisabled, self.tenant) - resp, content = header.request(url, "POST", body=body, - headers={"Content-Type": "application/xml", - "ACCEPT": "application/xml"}) - - content = etree.fromstring(content) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(403, int(resp['status'])) - self.assertEqual('application/xml', utils.content_type(resp)) - - def test_a_authorize_user_wrong(self): - header = httplib2.Http(".cache") - url = '%stokens' % utils.URL - body = {"passwordCredentials": {"username-w": "disabled", - "password": "secrete", - "tenantId": self.tenant}} - resp, content = header.request(url, "POST", body=json.dumps(body), - headers={"Content-Type": "application/json"}) - content = json.loads(content) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(400, int(resp['status'])) - self.assertEqual('application/json', utils.content_type(resp)) - - def test_a_authorize_user_wrong_xml(self): - header = httplib2.Http(".cache") - url = '%stokens' % utils.URL - body = ' \ - ' % self.tenant - resp, content = header.request(url, "POST", body=body, - headers={"Content-Type": "application/xml", - "ACCEPT": "application/xml"}) - content = etree.fromstring(content) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(400, int(resp['status'])) - self.assertEqual('application/xml', utils.content_type(resp)) - - -class MultiToken(unittest.TestCase): - - def setUp(self): - self.auth_token = utils.get_auth_token() - self.userdisabled = utils.get_userdisabled() - resp1, content1 = utils.create_tenant('test_tenant1', self.auth_token) - #create tenant2 - resp2, content2 = utils.create_tenant('test_tenant2', self.auth_token) - #create user1 with tenant1 - resp3, content3 = utils.create_user('test_tenant1', 'test_user1', - self.auth_token) - resp3, content3 = utils.create_user('test_tenant1', 'test_user2', - self.auth_token) - #add user1 to tenant2 - resp4, content4 = utils.add_user_json('test_tenant2', 'test_user1', - self.auth_token) - #self.exp_auth_token = utils.get_exp_auth_token() - #self.disabled_token = utils.get_disabled_token() - - def tearDown(self): - utils.delete_user('test_tenant1', 'test_user1', self.auth_token) - utils.delete_user('test_tenant1', 'test_user2', self.auth_token) - utils.delete_user('test_tenant2', 'test_user1', self.auth_token) - utils.delete_tenant('test_tenant1', self.auth_token) - utils.delete_tenant('test_tenant2', self.auth_token) - - """ INVALID TEST - we're changing how we delegate access to second tenant - def test_multi_token(self): - #get token for user1 with tenant1 - token1 = utils.get_token('test_user1', 'secrete', 'test_tenant1',\ - 'token') - #get token for user 1 with tenant2 - token2 = utils.get_token('test_user1', 'secrete', 'test_tenant2',\ - 'token') - #test result :: both token should be different - self.assertNotEqual(token1, None) - self.assertNotEqual(token2, None) - self.assertNotEqual(token1, token2) - - resp = utils.delete_token(token1, self.auth_token) - resp = utils.delete_token(token2, self.auth_token) - """ - - def test_unassigned_user(self): - resp, content = utils.get_token('test_user2', 'secrete', \ - 'test_tenant') - - self.assertEqual(401, int(resp['status'])) - -if __name__ == '__main__': - unittest.main() diff --git a/test/unit/test_authn_v2.py b/test/unit/test_authn_v2.py deleted file mode 100644 index af9d725b..00000000 --- a/test/unit/test_authn_v2.py +++ /dev/null @@ -1,463 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright (c) 2011 OpenStack, LLC. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import json -import logging - -from keystone import server -from test.unit import base -from test.unit.decorators import jsonify, xmlify - -logger = logging.getLogger('test.unit.test_authn_v2') - - -class AuthnMethods(object): - - def test_authn_get_fails(self): - """ - Test for GH issue #5. GET /tokens works when it should not - """ - url = "/tokens" - req = self.get_request('GET', url) - body = { - "passwordCredentials": { - "username": self.auth_user['id'], - "password": self.auth_user['password'], - "tenantId": self.auth_user['tenant_id'] - } - } - req.body = json.dumps(body) - self.get_response() - self.status_not_found() - - @jsonify - def test_authn_success_json(self): - """ - Test that good password credentials returns a 200 OK - """ - url = "/tokens" - req = self.get_request('POST', url) - body = { - "passwordCredentials": { - "username": self.auth_user['id'], - "password": self.auth_user['password'], - "tenantId": self.auth_user['tenant_id'] - } - } - req.body = json.dumps(body) - self.get_response() - self.status_ok() - - expected = { - u'auth': { - u'token': { - u'expires': self.expires.strftime("%Y-%m-%dT%H:%M:%S.%f"), - u'id': self.auth_token_id - } - } - } - self.assert_dict_equal(expected, json.loads(self.res.body)) - - @jsonify - def test_authn_success_missing_tenant_json(self): - """ - Test that supplying an existing user/pass, with a missing tenant ID - in the password credentials results in a 200 OK but a token not - matching the token with a tenant attached to it. - """ - # Create a special token for user with no tenant - auth_token = self.fixture_create_token( - user_id=self.auth_user['id'], - tenant_id=None, - expires=self.expires, - token_id='NOTENANTTOKEN') - - url = "/tokens" - req = self.get_request('POST', url) - body = { - "passwordCredentials": { - "username": self.auth_user['id'], - "password": self.auth_user['password'] - } - } - req.body = json.dumps(body) - self.get_response() - self.status_ok() - - expected = { - u'auth': { - u'token': { - u'expires': self.expires.strftime("%Y-%m-%dT%H:%M:%S.%f"), - u'id': 'NOTENANTTOKEN' - } - } - } - self.assert_dict_equal(expected, json.loads(self.res.body)) - - @jsonify - def test_authn_success_none_tenant_json(self): - """ - Test that supplying an existing user/pass, with a tenant ID of None - in the password credentials results in a 200 OK but a token not - matching the token with a tenant attached to it. - """ - # Create a special token for user with no tenant - auth_token = self.fixture_create_token( - user_id=self.auth_user['id'], - tenant_id=None, - expires=self.expires, - token_id='NOTENANTTOKEN') - - url = "/tokens" - req = self.get_request('POST', url) - body = { - "passwordCredentials": { - "username": self.auth_user['id'], - "password": self.auth_user['password'], - "tenantId": None - } - } - req.body = json.dumps(body) - self.get_response() - self.status_ok() - - expected = { - u'auth': { - u'token': { - u'expires': self.expires.strftime("%Y-%m-%dT%H:%M:%S.%f"), - u'id': 'NOTENANTTOKEN' - } - } - } - self.assert_dict_equal(expected, json.loads(self.res.body)) - - @jsonify - def test_authn_malformed_creds_json(self): - """ - Test that supplying a malformed password credentials - results in a 400 Bad Request - """ - url = "/tokens" - req = self.get_request('POST', url) - body = { - "passwordCredMisspelled": { - "username": 'unknown', - "password": 'badpass', - "tenantId": None - } - } - req.body = json.dumps(body) - self.get_response() - self.status_bad_request() - - @jsonify - def test_authn_user_not_found_json(self): - """ - Test that supplying a non-existing user in the password credentials - results in a 401 Unauthorized - """ - url = "/tokens" - req = self.get_request('POST', url) - body = { - "passwordCredentials": { - "username": 'unknown', - "password": 'badpass', - "tenantId": None - } - } - req.body = json.dumps(body) - self.get_response() - self.status_unauthorized() - - @jsonify - def test_authn_user_missing_json(self): - """ - Test that supplying a missing user in the password credentials - results in a 401 Unauthorized - """ - url = "/tokens" - req = self.get_request('POST', url) - body = { - "passwordCredentials": { - "username": None, - "password": self.auth_user['password'], - "tenantId": self.auth_user['tenant_id'] - } - } - req.body = json.dumps(body) - self.get_response() - self.status_unauthorized() - - @jsonify - def test_authn_bad_pass_json(self): - """ - Test that supplying an existing user and a bad password - in the password credentials results in a 401 Unauthorized - """ - url = "/tokens" - req = self.get_request('POST', url) - body = { - "passwordCredentials": { - "username": self.auth_user['id'], - "password": 'badpass', - "tenantId": None - } - } - req.body = json.dumps(body) - self.get_response() - self.status_unauthorized() - - @jsonify - def test_authn_bad_tenant_json(self): - """ - Test that supplying an existing user/pass, with a bad tenant ID - in the password credentials results in a 401 Unauthorized - """ - url = "/tokens" - req = self.get_request('POST', url) - body = { - "passwordCredentials": { - "username": self.auth_user['id'], - "password": self.auth_user['password'], - "tenantId": 'badtenant' - } - } - req.body = json.dumps(body) - self.get_response() - self.status_unauthorized() - - @xmlify - def test_authn_success_xml(self): - """ - Test that good password credentials returns a 200 OK - """ - url = "/tokens" - req = self.get_request('POST', url) - req.body = ' \ - ' % (self.auth_user['password'], - self.auth_user['id'], - self.auth_user['tenant_id']) - self.get_response() - self.status_ok() - - expected = """ - - - - """ % (self.expires.strftime("%Y-%m-%dT%H:%M:%S.%f"), - self.auth_token_id) - self.assert_xml_strings_equal(expected, self.res.body) - - @xmlify - def test_authn_success_missing_tenant_xml(self): - """ - Test that supplying an existing user/pass, with a missing tenant ID - in the password credentials results in a 200 OK but a token not - matching the token with a tenant attached to it. - """ - # Create a special token for user with no tenant - auth_token = self.fixture_create_token( - user_id=self.auth_user['id'], - tenant_id=None, - expires=self.expires, - token_id='NOTENANTTOKEN') - - url = "/tokens" - req = self.get_request('POST', url) - req.body = ' \ - ' % ( - self.auth_user['password'], - self.auth_user['id']) - self.get_response() - self.status_ok() - - expected = """ - - - - """ % (self.expires.strftime("%Y-%m-%dT%H:%M:%S.%f"), - 'NOTENANTTOKEN') - self.assert_xml_strings_equal(expected, self.res.body) - - @xmlify - def test_authn_malformed_creds_xml(self): - """ - Test that supplying a malformed password credentials - results in a 400 Bad Request - """ - url = "/tokens" - req = self.get_request('POST', url) - req.body = ' \ - ' % (self.auth_user['password'], - self.auth_user['id'], - self.auth_user['tenant_id']) - self.get_response() - self.status_bad_request() - - @xmlify - def test_authn_user_not_found_xml(self): - """ - Test that supplying a non-existing user in the password credentials - results in a 401 Unauthorized - """ - url = "/tokens" - req = self.get_request('POST', url) - req.body = ' \ - ' % (self.auth_user['password'], - 'missinguser', - self.auth_user['tenant_id']) - self.get_response() - self.status_unauthorized() - - @xmlify - def test_authn_user_missing_xml(self): - """ - Test that supplying a missing user in the password credentials - results in a 400 Bad Request - """ - url = "/tokens" - req = self.get_request('POST', url) - req.body = ' \ - ' % (self.auth_user['password'], - self.auth_user['tenant_id']) - self.get_response() - self.status_bad_request() - - @xmlify - def test_authn_bad_pass_xml(self): - """ - Test that supplying a bad password in the password credentials - results in a 401 Unauthorized - """ - url = "/tokens" - req = self.get_request('POST', url) - req.body = ' \ - ' % ('badpass', - self.auth_user['id'], - self.auth_user['tenant_id']) - self.get_response() - self.status_unauthorized() - - @xmlify - def test_authn_bad_tenant_xml(self): - """ - Test that supplying a bad tenant in the password credentials - results in a 401 Unauthorized - """ - url = "/tokens" - req = self.get_request('POST', url) - req.body = ' \ - ' % (self.auth_user['password'], - self.auth_user['id'], - 'badtenant') - self.get_response() - self.status_unauthorized() - - -class TestAuthnV2(base.ServiceAPITest, AuthnMethods): - - """ - Tests for the /v2.0/tokens auth endpoint with main service API - """ - - -class TestAdminAuthnV2(base.AdminAPITest, AuthnMethods): - - """ - Tests for the /v2.0/tokens auth endpoint with admin API - """ - - @jsonify - def test_validate_token_json(self): - """ - Test successful validation of the token we use in authn - """ - url = "/tokens/%s" % self.auth_token_id - headers = {"X-Auth-Token": self.auth_token_id} - req = self.get_request('GET', url, headers) - self.get_response() - self.status_ok() - - expected = { - "auth": { - "token": { - u'expires': self.expires.strftime("%Y-%m-%dT%H:%M:%S.%f"), - u'id': self.auth_token_id, - "tenantId": self.auth_user['tenant_id'] - }, - "user": { - "username": self.auth_user['id'], - "tenantId": self.auth_user['tenant_id'], - "roleRefs": [] - } - } - } - for user_role in self.auth_user['roles']: - expected["auth"]["user"]["roleRefs"].append( - {"roleId": user_role['role_id'], "id": user_role['id']}) - self.assert_dict_equal(expected, json.loads(self.res.body)) - - @xmlify - def test_validate_token_xml(self): - """ - Test successful validation of the token we use in authn - """ - url = "/tokens/%s" % self.auth_token_id - headers = {"X-Auth-Token": self.auth_token_id} - req = self.get_request('GET', url, headers) - self.get_response() - self.status_ok() - - expected = """ - - - - """ % ( - self.expires.strftime("%Y-%m-%dT%H:%M:%S.%f"), - self.auth_token_id, - self.auth_user['tenant_id'], - self.auth_user['id'], - self.auth_user['tenant_id']) - - for user_role in self.auth_user['roles']: - expected = expected + """ - """ % (user_role['id'], - user_role['role_id']) - expected = expected + """ - - """ - self.assert_xml_strings_equal(expected, self.res.body) diff --git a/test/unit/test_common.py b/test/unit/test_common.py deleted file mode 100755 index be017285..00000000 --- a/test/unit/test_common.py +++ /dev/null @@ -1,809 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright (c) 2010-2011 OpenStack, LLC. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -import httplib2 -import json -from lxml import etree -import os -import sys -sys.path.append(os.path.abspath(os.path.join(os.path.abspath(__file__), - '..', '..', '..', '..', 'keystone'))) -import unittest - -URL = 'http://localhost:8081/v2.0/' -URLv1 = 'http://localhost:8080/v1.0/' - -def get_token(user, pswd, tenant_id, kind=''): - header = httplib2.Http(".cache") - url = '%stokens' % URL - - if not tenant_id: - body = {"passwordCredentials": {"username": user, - "password": pswd}} - else: - body = {"passwordCredentials": {"username": user, - "password": pswd, - "tenantId": tenant_id}} - - resp, content = header.request(url, "POST", body=json.dumps(body), - headers={"Content-Type": "application/json"}) - - if int(resp['status']) == 200: - content = json.loads(content) - token = str(content['auth']['token']['id']) - else: - token = None - if kind == 'token': - return token - else: - return (resp, content) - - -def get_token_legacy(user, pswd, kind=''): - header = httplib2.Http(".cache") - url = URLv1 - resp, content = header.request(url, "GET", '', - headers={"Content-Type": "application/json", - "X-Auth-User": user, - "X-Auth-Key": pswd}) - - if int(resp['status']) == 204: - token = resp['x-auth-token'] - else: - token = None - if kind == 'token': - return token - else: - return (resp, content) - - -def delete_token(token, auth_token): - header = httplib2.Http(".cache") - url = '%stoken/%s' % (URL, token) - resp, content = header.request(url, "DELETE", body='', - headers={"Content-Type": "application/json", - "X-Auth-Token": auth_token}) - return (resp, content) - - -def create_tenant(tenantid, auth_token): - header = httplib2.Http(".cache") - - url = '%stenants' % (URL) - body = {"tenant": {"id": tenantid, - "description": "A description ...", - "enabled": True}} - resp, content = header.request(url, "POST", body=json.dumps(body), - headers={"Content-Type": "application/json", - "X-Auth-Token": auth_token}) - return (resp, content) - - -def create_tenant_group(groupid, tenantid, auth_token): - header = httplib2.Http(".cache") - - url = '%stenants/%s/groups' % (URL, tenantid) - body = {"group": {"id": groupid, - "description": "A description ..."}} - resp, content = header.request(url, "POST", body=json.dumps(body), - headers={"Content-Type": "application/json", - "X-Auth-Token": auth_token}) - return (resp, content) - - -def delete_tenant(tenantid, auth_token): - header = httplib2.Http(".cache") - url = '%stenants/%s' % (URL, tenantid) - resp, content = header.request(url, "DELETE", body='{}', - headers={"Content-Type": "application/json", - "X-Auth-Token": auth_token}) - return resp - - -def delete_tenant_group(groupid, tenantid, auth_token): - header = httplib2.Http(".cache") - url = '%stenants/%s/groups/%s' % (URL, tenantid, groupid) - resp, content = header.request(url, "DELETE", body='{}', - headers={"Content-Type": "application/json", - "X-Auth-Token": auth_token}) - return (resp, content) - - -def create_global_group(groupid, auth_token): - header = httplib2.Http(".cache") - - url = '%sgroups' % (URL) - body = {"group": {"id": groupid, - "description": "A description ..."}} - resp, content = header.request(url, "POST", body=json.dumps(body), - - headers={"Content-Type": "application/json", - "X-Auth-Token": auth_token}) - return (resp, content) - - -def create_global_group_xml(groupid, auth_token): - header = httplib2.Http(".cache") - url = '%sgroups' % (URL) - body = '\ - A Description of the group\ - ' % groupid - resp, content = header.request(url, "POST", body=body, - headers={"Content-Type": "application/xml", - "X-Auth-Token": auth_token, - "ACCEPT": "application/xml"}) - return (resp, content) - - -def delete_global_group(groupid, auth_token): - header = httplib2.Http(".cache") - url = '%sgroups/%s' % (URL, groupid) - resp, content = header.request(url, "DELETE", body='{}', - headers={"Content-Type": "application/json", - "X-Auth-Token": auth_token}) - return (resp, content) - - -def delete_global_group_xml(groupid, auth_token): - header = httplib2.Http(".cache") - url = '%sgroups/%s' % (URL, groupid) - resp, content = header.request(url, "DELETE", body='', - headers={"Content-Type": "application/xml", - "X-Auth-Token": auth_token, - "ACCEPT": "application/xml"}) - return (resp, content) - - -def get_token_xml(user, pswd, tenant_id, type=''): - header = httplib2.Http(".cache") - url = '%stokens' % URL - # to test multi token, removing below code - """if tenant_id: - body = ' \ - ' % (pswd, user, tenant_id) - else: - body = ' \ - ' % (pswd, user)""" - # adding code ie., body - body = ' \ - ' % (pswd, user, tenant_id) - resp, content = header.request(url, "POST", body=body, - headers={"Content-Type": "application/xml", - "ACCEPT": "application/xml"}) - if int(resp['status']) == 200: - dom = etree.fromstring(content) - root = dom.find("{http://docs.openstack.org/" \ - "identity/api/v2.0}token") - token_root = root.attrib - token = str(token_root['id']) - else: - token = None - - if type == 'token': - return token - else: - return (resp, content) - - -def delete_token_xml(token, auth_token): - header = httplib2.Http(".cache") - url = '%stoken/%s' % (URL, token) - resp, content = header.request(url, "DELETE", body='', - headers={"Content-Type": "application/xml", - "X-Auth-Token": auth_token, - "ACCEPT": "application/xml"}) - return (resp, content) - - -def create_tenant_xml(tenantid, auth_token): - header = httplib2.Http(".cache") - url = '%stenants' % (URL) - body = ' \ - \ - A description... \ - ' % tenantid - resp, content = header.request(url, "POST", body=body, - headers={"Content-Type": "application/xml", - "X-Auth-Token": auth_token, - "ACCEPT": "application/xml"}) - return (resp, content) - - -def create_tenant_group_xml(groupid, tenantid, auth_token): - header = httplib2.Http(".cache") - url = '%stenants/%s/groups' % (URL, tenantid) - body = ' \ - \ - A description... \ - ' % groupid - resp, content = header.request(url, "POST", body=body, - headers={"Content-Type": "application/xml", - "X-Auth-Token": auth_token, - "ACCEPT": "application/xml"}) - return (resp, content) - - -def delete_tenant_xml(tenantid, auth_token): - header = httplib2.Http(".cache") - url = '%stenants/%s' % (URL, tenantid) - resp, content = header.request(url, "DELETE", body='', - headers={"Content-Type": "application/xml", - "X-Auth-Token": auth_token, - "ACCEPT": "application/xml"}) - - return resp - - -def delete_tenant_group_xml(groupid, tenantid, auth_token): - header = httplib2.Http(".cache") - url = '%stenant/%s/groups/%s' % (URL, tenantid, groupid) - resp, content = header.request(url, "DELETE", body='', - headers={"Content-Type": "application/xml", - "X-Auth-Token": auth_token, - "ACCEPT": "application/xml"}) - return (resp, content) - - -def create_user(tenantid, userid, auth_token, email=None): - header = httplib2.Http(".cache") - url = '%stenants/%s/users' % (URL, tenantid) - if email is not None: - email_id = email - else: - email_id = "%s@rackspace.com" % userid - body = {"user": {"password": "secrete", - "id": userid, - "tenantId": tenantid, - "email": "%s" % email_id, - "enabled": True}} - resp, content = header.request(url, "POST", body=json.dumps(body), - headers={"Content-Type": "application/json", - "X-Auth-Token": auth_token}) - return (resp, content) - - -def delete_user(tenant, userid, auth_token): - header = httplib2.Http(".cache") - url = '%stenants/%s/users/%s' % (URL, tenant, userid) - resp, content = header.request(url, "DELETE", body='{}', - headers={"Content-Type": "application/json", - "X-Auth-Token": auth_token}) - return resp - - -def create_user_xml(tenantid, userid, auth_token, email=None): - header = httplib2.Http(".cache") - url = '%stenants/%s/users' % (URL, tenantid) - if email is not None: - email_id = email - else: - email_id = userid - body = ' \ - ' % (email_id, tenantid, userid) - resp, content = header.request(url, "POST", body=body, - headers={"Content-Type": "application/xml", - "X-Auth-Token": auth_token, - "ACCEPT": "application/xml"}) - return (resp, content) - - -"""def delete_user(tenant, userid, auth_token): - h = httplib2.Http(".cache") - url = '%stenants/%s/users/%s' % (URL, tenant, userid) - - resp, content = h.request(url, "DELETE", body='{}', - headers={"Content-Type": "application/json", - "X-Auth-Token": auth_token}) - return resp""" - - -def delete_user_xml(tenantid, userid, auth_token): - header = httplib2.Http(".cache") - url = '%stenants/%s/users/%s' % (URL, tenantid, userid) - resp, content = header.request(url, "DELETE", body='', - headers={"Content-Type": "application/xml", - "X-Auth-Token": auth_token, - "ACCEPT": "application/xml"}) - return resp - - -def add_user_json(tenantid, userid, auth_token): - header = httplib2.Http(".cache") - url = '%stenants/%s/users/%s/add' % (URL, tenantid, userid) - resp, content = header.request(url, "PUT", body='{}', - headers={"Content-Type": "application/json", - "X-Auth-Token": auth_token}) - return (resp, content) - -def add_user_xml(tenantid, userid, auth_token): - header = httplib2.Http(".cache") - url = '%stenants/%s/users/%s/add' % (URL, tenantid, userid) - resp, content = header.request(url, "PUT", body='{}', - headers={"Content-Type": "application/xml", - "X-Auth-Token": auth_token, - "ACCEPT": "application/xml"}) - return (resp, content) - -def add_user_json(tenantid, userid, auth_token): - header = httplib2.Http(".cache") - url = '%stenants/%s/users/' % (URL, tenantid) - resp, content = header.request(url, "POST", body='{}', - headers={"Content-Type": "application/json", - "X-Auth-Token": auth_token}) - return (resp, content) - - -def add_user_xml(tenantid, userid, auth_token): - header = httplib2.Http(".cache") - url = '%stenants/%s/users/%s/add' % (URL, tenantid, userid) - resp, content = header.request(url, "PUT", body='{}', - headers={"Content-Type": "application/xml", - "X-Auth-Token": auth_token, - "ACCEPT": "application/xml"}) - return (resp, content) - - -def user_update_json(tenant_id, user_id, auth_token, email=None): - h = httplib2.Http(".cache") - url = '%stenants/%s/users/%s' % (URL, tenant_id, user_id) - if email is None: - new_email = "updatedjoeuser@rackspace.com" - else: - new_email = email - data = '{"user": { "email": "%s"}}' % (new_email) - resp, content = h.request(url, "PUT", body=data, - headers={"Content-Type": "application/json", - "X-Auth-Token": auth_token}) - return (resp, content) - - -def user_update_xml(tenant_id, user_id, auth_token, email=None): - h = httplib2.Http(".cache") - url = '%stenants/%s/users/%s' % (URL, tenant_id, user_id) - if email is None: - new_email = "updatedjoeuser@rackspace.com" - else: - new_email = email - data = ' \ - ' % (new_email) - resp, content = h.request(url, "PUT", body=data, - headers={"Content-Type": "application/xml", - "X-Auth-Token": auth_token, - "ACCEPT": "application/xml"}) - return (resp, content) - - -def user_get_json(tenant_id, user_id, auth_token): - h = httplib2.Http(".cache") - url = '%stenants/%s/users/%s' % (URL, tenant_id, user_id) - #test for Content-Type = application/json - resp, content = h.request(url, "GET", body='{}', - headers={"Content-Type": "application/json", - "X-Auth-Token": auth_token}) - return (resp, content) - - -def user_password_json(tenant_id, user_id, auth_token): - h = httplib2.Http(".cache") - url = '%stenants/%s/users/%s/password' % (URL, tenant_id, user_id) - data = '{"user": { "password": "p@ssword"}}' - resp, content = h.request(url, "PUT", body=data, - headers={"Content-Type": "application/json", - "X-Auth-Token": auth_token}) - return (resp, content) - - -def user_password_xml(tenant_id, user_id, auth_token): - h = httplib2.Http(".cache") - url = '%stenants/%s/users/%s/password' % (URL, tenant_id, user_id) - data = ' \ - ' - resp, content = h.request(url, "PUT", body=data, - headers={"Content-Type": "application/xml", - "X-Auth-Token": auth_token, - "ACCEPT": "application/xml"}) - return (resp, content) - - -def user_enabled_json(tenant_id, user_id, auth_token): - h = httplib2.Http(".cache") - url = '%stenants/%s/users/%s/enabled' % (URL, tenant_id, user_id) - data = {"user": {"enabled": True}} - resp, content = h.request(url, "PUT", body=json.dumps(data), - headers={"Content-Type": "application/json", - "X-Auth-Token": auth_token}) - return (resp, content) - - -def user_enabled_xml(tenant_id, user_id, auth_token): - h = httplib2.Http(".cache") - url = '%stenants/%s/users/%s/enabled' % (URL, tenant_id, user_id) - data = ' \ - ' - resp, content = h.request(url, "PUT", body=data, - headers={"Content-Type": "application/xml", - "X-Auth-Token": auth_token, - "ACCEPT": "application/xml"}) - return (resp, content) - - -def user_get_xml(tenant_id, user_id, auth_token): - h = httplib2.Http(".cache") - url = '%stenants/%s/users/%s' % (URL, tenant_id, user_id) - resp, content = h.request(url, "GET", body='{}', - headers={"Content-Type": "application/xml", - "X-Auth-Token": auth_token, - "ACCEPT": "application/xml"}) - return (resp, content) - - -def users_get_json(tenant_id, auth_token): - h = httplib2.Http(".cache") - url = '%stenants/%s/users' % (URL, tenant_id) - resp, content = h.request(url, "GET", body='{}', - headers={"Content-Type": "application/json", - "X-Auth-Token": auth_token}) - return (resp, content) - - -def users_get_xml(tenant_id, auth_token): - h = httplib2.Http(".cache") - url = '%stenants/%s/users' % (URL, tenant_id) - resp, content = h.request(url, "GET", body='{}', - headers={"Content-Type": "application/xml", - "X-Auth-Token": auth_token, - "ACCEPT": "application/xml"}) - return (resp, content) - - -def users_group_get_json(tenant_id, user_id, auth_token): - h = httplib2.Http(".cache") - url = '%stenants/%s/users/%s/groups' % (URL, tenant_id, user_id) - resp, content = h.request(url, "GET", body='{}', - headers={"Content-Type": "application/json", - "X-Auth-Token": auth_token}) - return (resp, content) - - -def users_group_get_xml(tenant_id, user_id, auth_token): - h = httplib2.Http(".cache") - url = '%stenants/%s/users/%s/groups' % (URL, tenant_id, user_id) - resp, content = h.request(url, "GET", body='{}', - headers={"Content-Type": "application/xml", - "X-Auth-Token": auth_token, - "ACCEPT": "application/xml"}) - return (resp, content) - - -def add_user_tenant_group(tenantid, groupid, userid, auth_token): - header = httplib2.Http(".cache") - url = '%stenants/%s/groups/%s/users/%s' % (URL, tenantid, groupid, userid) - - resp, content = header.request(url, "PUT", body='', - headers={"Content-Type": "application/json", - "X-Auth-Token": auth_token}) - return (resp, content) - - -def add_user_tenant_group_xml(tenantid, groupid, userid, auth_token): - header = httplib2.Http(".cache") - url = '%stenants/%s/groups/%s/users/%s' % (URL, tenantid, groupid, userid) - - resp, content = header.request(url, "PUT", body='', - headers={"Content-Type": "application/xml", - "X-Auth-Token": auth_token, - "ACCEPT": "application/xml"}) - return (resp, content) - - -def delete_user_tenant_group(tenantid, groupid, userid, auth_token): - header = httplib2.Http(".cache") - url = '%stenants/%s/groups/%s/users/%s' % (URL, tenantid, groupid, userid) - - resp, content = header.request(url, "DELETE", body='', - headers={"Content-Type": "application/json", - "X-Auth-Token": auth_token}) - return (resp, content) - - -def delete_user_tenant_group_xml(tenantid, groupid, userid, auth_token): - header = httplib2.Http(".cache") - url = '%stenants/%s/groups/%s/users/%s' % (URL, tenantid, groupid, userid) - - resp, content = header.request(url, "DELETE", body='', - headers={"Content-Type": "application/xml", - "X-Auth-Token": auth_token, - "ACCEPT": "application/xml"}) - return (resp, content) - - -def get_user_tenant_group(tenantid, groupid, auth_token): - header = httplib2.Http(".cache") - url = '%stenants/%s/groups/%s/users' % (URL, tenantid, groupid) - - resp, content = header.request(url, "GET", body='', - headers={"Content-Type": "application/json", - "X-Auth-Token": auth_token}) - return (resp, content) - - -def get_user_tenant_group_xml(tenantid, groupid, auth_token): - header = httplib2.Http(".cache") - url = '%stenants/%s/groups/%s/users' % (URL, tenantid, groupid) - - resp, content = header.request(url, "GET", body='', - headers={"Content-Type": "application/xml", - "X-Auth-Token": auth_token, - "ACCEPT": "application/xml"}) - return (resp, content) - - -def add_user_global_group(groupid, userid, auth_token): - header = httplib2.Http(".cache") - url = '%sgroups/%s/users/%s' % (URL, groupid, userid) - - resp, content = header.request(url, "PUT", body='', - headers={"Content-Type": "application/json", - "X-Auth-Token": auth_token}) - return (resp, content) - - -def add_user_global_group_xml(groupid, userid, auth_token): - header = httplib2.Http(".cache") - url = '%sgroups/%s/users/%s' % (URL, groupid, userid) - - resp, content = header.request(url, "PUT", body='', - headers={"Content-Type": "application/xml", - "X-Auth-Token": auth_token, - "ACCEPT": "application/xml"}) - return (resp, content) - - -def delete_user_global_group(groupid, userid, auth_token): - header = httplib2.Http(".cache") - url = '%sgroups/%s/users/%s' % (URL, groupid, userid) - - resp, content = header.request(url, "DELETE", body='', - headers={"Content-Type": "application/json", - "X-Auth-Token": auth_token}) - return (resp, content) - - -def delete_user_global_group_xml(groupid, userid, auth_token): - header = httplib2.Http(".cache") - url = '%sgroups/%s/users/%s' % (URL, groupid, userid) - - resp, content = header.request(url, "DELETE", body='', - headers={"Content-Type": "application/xml", - "X-Auth-Token": auth_token, - "ACCEPT": "application/xml"}) - return (resp, content) - - -def get_user_global_group(groupid, auth_token): - header = httplib2.Http(".cache") - url = '%sgroups/%s/users' % (URL, groupid) - - resp, content = header.request(url, "GET", body='', - headers={"Content-Type": "application/json", - "X-Auth-Token": auth_token}) - - return (resp, content) - - -def get_userid(): - return 'test_user11' - - -def get_password(): - return 'secrete' - - -def get_email(): - return 'joetest@rackspace.com' - - -def get_user_global_group_xml(groupid, auth_token): - header = httplib2.Http(".cache") - url = '%sgroups/%s/users' % (URL, groupid) - - resp, content = header.request(url, "GET", body='', - headers={"Content-Type": "application/xml", - "X-Auth-Token": auth_token, - "ACCEPT": "application/xml"}) - return (resp, content) - - -def get_tenant(): - return '1234' - - -def get_another_tenant(): - return '4321' - - -def get_user(): - return 'test_user' - - -def get_userdisabled(): - return 'disabled' - - -def get_auth_token(): - return '999888777666' - - -def get_exp_auth_token(): - return '000999' - - -def get_none_token(): - return '' - - -def get_non_existing_token(): - return 'invalid_token' - - -def get_disabled_token(): - return '999888777' - - -def content_type(resp): - return resp['content-type'].split(';')[0] - - -def get_global_tenant(): - return 'GlobalTenant' - - -def handle_user_resp(self, content, respvalue, resptype): - if respvalue == 200: - if resptype == 'application/json': - content = json.loads(content) - if 'tenantId' in content['user']: - self.tenant = content['user']['tenantId'] - self.userid = content['user']['id'] - if resptype == 'application/xml': - content = etree.fromstring(content) - self.tenant = content.get("tenantId") - self.id = content.get("id") - if respvalue == 500: - self.fail('Identity Fault') - elif respvalue == 503: - self.fail('Service Not Available') - -def create_role(roleid, auth_token): - header = httplib2.Http(".cache") - - url = '%sroles' % (URL) - body = {"role": {"id": roleid, - "description": "A description ..."}} - resp, content = header.request(url, "POST", body=json.dumps(body), - headers={"Content-Type": "application/json", - "X-Auth-Token": auth_token}) - return (resp, content) - -def create_role_ref(user_id, role_id, tenant_id, auth_token): - header = httplib2.Http(".cache") - - url = '%susers/%s/roleRefs' % (URL, user_id) - body = {"roleRef": {"tenantId": tenant_id, - "roleId": role_id}} - resp, content = header.request(url, "POST", body=json.dumps(body), - headers={"Content-Type": "application/json", - "X-Auth-Token": auth_token}) - return (resp, content) - -def create_role_ref_xml(user_id, role_id, tenant_id, auth_token): - header = httplib2.Http(".cache") - url = '%susers/%s/roleRefs' % (URL, user_id) - body = '\ - \ - ' % (tenant_id, role_id) - resp, content = header.request(url, "POST", body=body, - headers={"Content-Type": "application/xml", - "X-Auth-Token": auth_token, - "ACCEPT": "application/xml"}) - return (resp, content) - -def delete_role_ref(user, role_ref_id, auth_token): - header = httplib2.Http(".cache") - url = '%susers/%s/roleRefs/%s' % (URL, user, role_ref_id) - resp, content = header.request(url, "DELETE", body='', - headers={"Content-Type": "application/json", - "X-Auth-Token": str(auth_token)}) - return (resp, content) - -def create_role_xml(role_id, auth_token): - header = httplib2.Http(".cache") - url = '%sroles' % (URL) - body = '\ - \ - ' % role_id - resp, content = header.request(url, "POST", body=body, - headers={"Content-Type": "application/xml", - "X-Auth-Token": auth_token, - "ACCEPT": "application/xml"}) - return (resp, content) - -def create_baseurls_ref(tenant_id, baseurl_id, auth_token): - header = httplib2.Http(".cache") - - url = '%stenants/%s/baseURLRefs' % (URL, tenant_id) - body = {"baseURL": {"id": baseurl_id}} - resp, content = header.request(url, "POST", body=json.dumps(body), - headers={"Content-Type": "application/json", - "X-Auth-Token": auth_token}) - return (resp, content) - -def create_baseurls_ref_xml(tenant_id, baseurl_id, auth_token): - header = httplib2.Http(".cache") - url = '%stenants/%s/baseURLRefs' % (URL, tenant_id) - body = '\ - \ - ' % (baseurl_id) - resp, content = header.request(url, "POST", body=body, - headers={"Content-Type": "application/xml", - "X-Auth-Token": auth_token, - "ACCEPT": "application/xml"}) - return (resp, content) - -def delete_all_baseurls_ref(tenant_id, auth_token): - header = httplib2.Http(".cache") - url = '%stenants/%s/baseURLRefs' % (URL, tenant_id) - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body='{}', - headers={"Content-Type": "application/json", - "X-Auth-Token": auth_token}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - - #verify content - obj = json.loads(content) - base_url_refs = obj["baseURLRefs"]["values"] - for base_url_ref in base_url_refs: - url = '%stenants/%s/baseURLRefs/%s' % (URL, tenant_id, base_url_ref["id"]) - header.request(url, "DELETE", body='', - headers={"Content-Type": "application/json", - "X-Auth-Token": str(auth_token)}) - -if __name__ == '__main__': - unittest.main() \ No newline at end of file diff --git a/test/unit/test_exthandler.py b/test/unit/test_exthandler.py deleted file mode 100644 index 4379e03f..00000000 --- a/test/unit/test_exthandler.py +++ /dev/null @@ -1,65 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright (c) 2010-2011 OpenStack, LLC. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import os -import sys -# Need to access identity module -sys.path.append(os.path.abspath(os.path.join( - os.getcwd(), '..', '..', 'keystone'))) -from queryext.exthandler import UrlExtensionFilter -import unittest - - -class MockWsgiApp(object): - - def __init__(self): - pass - - def __call__(self, env, start_response): - pass - - -def _start_response(): - pass - - -class UrlExtensionFilterTest(unittest.TestCase): - - def setUp(self): - self.filter = UrlExtensionFilter(MockWsgiApp(), {}) - - def test_xml_extension(self): - env = {'PATH_INFO': '/v2.0/someresource.xml'} - self.filter(env, _start_response) - self.assertEqual('/v2.0/someresource', env['PATH_INFO']) - self.assertEqual('application/xml', env['HTTP_ACCEPT']) - - def test_json_extension(self): - env = {'PATH_INFO': '/v2.0/someresource.json'} - self.filter(env, _start_response) - self.assertEqual('/v2.0/someresource', env['PATH_INFO']) - self.assertEqual('application/json', env['HTTP_ACCEPT']) - - def test_extension_overrides_header(self): - env = {'PATH_INFO': '/v2.0/someresource.json', - 'HTTP_ACCEPT': 'application/xml'} - self.filter(env, _start_response) - self.assertEqual('/v2.0/someresource', env['PATH_INFO']) - self.assertEqual('application/json', env['HTTP_ACCEPT']) - - -if __name__ == '__main__': - unittest.main() diff --git a/test/unit/test_groups.py b/test/unit/test_groups.py deleted file mode 100644 index 2d7a7e00..00000000 --- a/test/unit/test_groups.py +++ /dev/null @@ -1,966 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright (c) 2010-2011 OpenStack, LLC. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -import httplib2 -import json -from lxml import etree -import os -import sys -sys.path.append(os.path.abspath(os.path.join(os.path.abspath(__file__), - '..', '..', '..', '..', 'keystone'))) -import unittest -from webtest import TestApp - -import test_common as utils - - -## -## Global Group Tests -## - - -class GlobalGroupTest(unittest.TestCase): - - def setUp(self): - self.globaltenant = utils.get_global_tenant() - self.user = utils.get_user() - self.userdisabled = utils.get_userdisabled() - self.auth_token = utils.get_auth_token() - self.exp_auth_token = utils.get_exp_auth_token() - self.disabled_token = utils.get_disabled_token() - self.global_group = 'test_global_group_add' - utils.create_tenant(self.globaltenant, str(self.auth_token)) - utils.create_user(self.globaltenant, self.user, self.auth_token) - utils.add_user_json(self.globaltenant, self.user, self.auth_token) - self.token = utils.get_token(self.user, 'secrete', self.globaltenant, - 'token') - - def tearDown(self): - utils.delete_user(self.globaltenant, self.user, str(self.auth_token)) - utils.delete_global_group(self.global_group, self.auth_token) - utils.delete_tenant(self.globaltenant, self.auth_token) - - -class CreateGlobalGroupTest(GlobalGroupTest): - - def test_global_group_create(self): - utils.delete_global_group(self.global_group, str(self.auth_token)) - resp_new, content_new = utils.create_global_group(self.global_group, - str(self.auth_token)) - - if int(resp_new['status']) == 500: - self.fail('Identity fault') - elif int(resp_new['status']) == 503: - self.fail('Service Not Available') - if int(resp_new['status']) not in (200, 201): - self.fail('Failed due to %d' % int(resp_new['status'])) - - def test_global_group_create_xml(self): - utils.delete_global_group_xml(self.global_group, str(self.auth_token)) - resp_new, content_new = utils.create_global_group_xml(\ - self.global_group, - str(self.auth_token)) - - if int(resp_new['status']) == 500: - self.fail('Identity fault') - elif int(resp_new['status']) == 503: - self.fail('Service Not Available') - - if int(resp_new['status']) not in (200, 201): - self.fail('Failed due to %d' % int(resp_new['status'])) - - def test_global_group_create_again(self): - utils.create_global_group(self.global_group, str(self.auth_token)) - resp_new, content_new = utils.create_global_group(self.global_group, - str(self.auth_token)) - if int(resp_new['status']) == 500: - self.fail('Identity fault') - elif int(resp_new['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(409, int(resp_new['status'])) - - def test_global_group_create_again_xml(self): - utils.create_global_group_xml(self.global_group, str(self.auth_token)) - resp_new, content_new = utils.create_global_group_xml(\ - self.global_group, - str(self.auth_token)) - content_new = etree.fromstring(content_new) - if int(resp_new['status']) == 500: - self.fail('Identity fault') - elif int(resp_new['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(409, int(resp_new['status'])) - - def test_global_group_create_unauthorized_token(self): - header = httplib2.Http(".cache") - resp, content = utils.create_global_group(\ - self.global_group, - str(self.token)) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(401, int(resp['status'])) - - def test_global_group_create_unauthorized_token_xml(self): - header = httplib2.Http(".cache") - resp, content = utils.create_global_group_xml(\ - self.global_group, - str(self.token)) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(401, int(resp['status'])) - - def test_global_group_create_expired_token(self): - header = httplib2.Http(".cache") - url = '%sgroups' % (utils.URL) - body = {"group": {"id": self.global_group, - "description": "A description ..."}} - resp, content = header.request(url, "POST", body=json.dumps(body), - headers={"Content-Type": "application/json", - "X-Auth-Token": \ - self.exp_auth_token}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(403, int(resp['status'])) - - def test_global_group_create_expired_token_xml(self): - header = httplib2.Http(".cache") - url = '%sgroups' % (utils.URL) - body = ' \ - A description... \ - ' % self.globaltenant - resp, content = header.request(url, "POST", body=body, - headers={"Content-Type": "application/xml", - "X-Auth-Token": self.exp_auth_token, - "ACCEPT": "application/xml"}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(403, int(resp['status'])) - - def test_global_group_create_missing_token(self): - header = httplib2.Http(".cache") - url = '%sgroups' % (utils.URL) - body = {"group": {"id": self.global_group, - "description": "A description ..."}} - resp, content = header.request(url, "POST", body=json.dumps(body), - headers={"Content-Type": "application/json"}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(401, int(resp['status'])) - - def test_global_group_create_missing_token_xml(self): - header = httplib2.Http(".cache") - url = '%sgroups' % (utils.URL) - body = ' \ - A description... \ - ' % self.global_group - resp, content = header.request(url, "POST", body=body, - headers={"Content-Type": "application/xml", - "ACCEPT": "application/xml"}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(401, int(resp['status'])) - - def test_global_group_create_disabled_token(self): - header = httplib2.Http(".cache") - url = '%sgroups' % (utils.URL) - body = '{"group": { "id": "%s", \ - "description": "A description ..." } }' % self.global_group - resp, content = header.request(url, "POST", body=body, - headers={"Content-Type": "application/json", - "X-Auth-Token": \ - self.disabled_token}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(403, int(resp['status'])) - - def test_global_group_create_disabled_token_xml(self): - header = httplib2.Http(".cache") - url = '%sgroups' % (utils.URL) - body = ' \ - A description... \ - ' % self.global_group - resp, content = header.request(url, "POST", body=body, - headers={"Content-Type": "application/xml", - "X-Auth-Token": self.disabled_token, - "ACCEPT": "application/xml"}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(403, int(resp['status'])) - - def test_global_group_create_invalid_token(self): - header = httplib2.Http(".cache") - url = '%sgroups' % (utils.URL) - body = '{"group": { "id": "%s", \ - "description": "A description ..." } }' % self.globaltenant - resp, content = header.request(url, "POST", body=body, - headers={"Content-Type": "application/json", - "X-Auth-Token": 'nonexsitingtoken'}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(404, int(resp['status'])) - - def test_global_group_create_invalid_token_xml(self): - header = httplib2.Http(".cache") - url = '%sgroups' % (utils.URL) - body = ' \ - A description... \ - ' % self.global_group - resp, content = header.request(url, "POST", body=body, - headers={"Content-Type": "application/xml", - "X-Auth-Token": 'nonexsitingtoken', - "ACCEPT": "application/xml"}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(404, int(resp['status'])) - - -class GetGlobalGroupsTest(GlobalGroupTest): - - def test_get_global_groups(self): - header = httplib2.Http(".cache") - utils.delete_global_group(self.global_group, str(self.auth_token)) - resp_new, content_new = utils.create_global_group(self.global_group, - str(self.auth_token)) - - url = '%sgroups' % (utils.URL) - resp, content = header.request(url, "GET", body='{}', - headers={"Content-Type": "application/json", - "X-Auth-Token": self.auth_token}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(200, int(resp['status'])) - - def test_get_global_groups_xml(self): - header = httplib2.Http(".cache") - utils.create_global_group_xml(self.global_group, str(self.auth_token)) - url = '%sgroups' % (utils.URL) - resp, content = header.request(url, "GET", body='', - headers={"Content-Type": "application/xml", - "X-Auth-Token": self.auth_token, - "ACCEPT": "application/xml"}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(200, int(resp['status'])) - - def test_get_global_groups_unauthorized_token(self): - header = httplib2.Http(".cache") - resp_new, content_new = utils.create_global_group(self.global_group, - str(self.auth_token)) - url = '%sgroups' % (utils.URL) - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body='{}', - headers={"Content-Type": "application/json", - "X-Auth-Token": self.token}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(401, int(resp['status'])) - - def test_get_global_groups_unauthorized_token_xml(self): - header = httplib2.Http(".cache") - resp_new, content_new = utils.create_global_group_xml(\ - self.global_group, - str(self.auth_token)) - url = '%sgroups' % (utils.URL) - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body='', - headers={"Content-Type": "application/xml", - "X-Auth-Token": self.token, - "ACCEPT": "application/xml"}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(401, int(resp['status'])) - - def test_get_global_groups_exp_token(self): - header = httplib2.Http(".cache") - resp_new, content_new = utils.create_global_group(self.global_group, - str(self.auth_token)) - url = '%sgroups' % (utils.URL) - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body='{}', - headers={"Content-Type": "application/json", - "X-Auth-Token": \ - self.exp_auth_token}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(403, int(resp['status'])) - - def test_get_global_groups_exp_token_xml(self): - header = httplib2.Http(".cache") - resp_new, content_new = utils.create_global_group_xml(\ - self.global_group, - str(self.auth_token)) - url = '%sgroups' % (utils.URL) - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body='', - headers={"Content-Type": "application/xml", - "X-Auth-Token": self.exp_auth_token, - "ACCEPT": "application/xml"}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(403, int(resp['status'])) - - -class GetGlobalGroupTest(GlobalGroupTest): - - def test_get_global_group(self): - header = httplib2.Http(".cache") - resp_new, content_new = utils.create_global_group(self.global_group, - str(self.auth_token)) - url = '%sgroups/%s' % (utils.URL, self.global_group) - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body='{}', - headers={"Content-Type": "application/json", - "X-Auth-Token": self.auth_token}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(200, int(resp['status'])) - - def test_get_global_group_xml(self): - header = httplib2.Http(".cache") - resp_new, content_new = utils.create_global_group_xml(\ - self.global_group, - str(self.auth_token)) - url = '%sgroups/%s' % (utils.URL, self.global_group) - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body='', - headers={"Content-Type": "application/xml", - "X-Auth-Token": self.auth_token, - "ACCEPT": "application/xml"}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(200, int(resp['status'])) - - def test_get_global_group_bad(self): - header = httplib2.Http(".cache") - resp_new, content_new = utils.create_global_group(self.global_group, - str(self.auth_token)) - url = '%sgroups/%s' % (utils.URL, 'global_group_bad') - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body='', - headers={"Content-Type": "application/json", - "X-Auth-Token": self.auth_token}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(404, int(resp['status'])) - - def test_get_global_group_bad_xml(self): - header = httplib2.Http(".cache") - resp_new, content_new = utils.create_global_group_xml(\ - self.global_group, - str(self.auth_token)) - url = '%sgroups/%s' % (utils.URL, 'global_group_bad') - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body='', - headers={"Content-Type": "application/xml", - "X-Auth-Token": self.auth_token, - "ACCEPT": "application/xml"}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(404, int(resp['status'])) - - -class UpdateGlobalGroupsTest(GlobalGroupTest): - - def test_update_global_group(self): - header = httplib2.Http(".cache") - resp_new, content_new = utils.create_global_group(self.global_group, - str(self.auth_token)) - url = '%sgroups/%s' % (utils.URL, self.global_group) - resp, content = header.request(url, "PUT", body='{"group":{\ - "id" : "%s","description" :\ - "A New description of the group..."}}' % self.global_group, - headers={"Content-Type": "application/json", - "X-Auth-Token": self.auth_token}) - body = json.loads(content) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(200, int(resp['status'])) - self.assertEqual(self.global_group, body['group']['id']) - self.assertEqual('A New description of the group...', - str(body['group']['description'])) - - def test_update_global_group_xml(self): - header = httplib2.Http(".cache") - resp_new, content_new = utils.create_global_group(self.global_group, - str(self.auth_token)) - - url = '%sgroups/%s' % (utils.URL, self.global_group) - data = u' \ - A NEW description... \ - ' % (self.global_group) - #test for Content-Type = application/json - resp, content = header.request(url, "PUT", body=data, - headers={"Content-Type": "application/xml", - "X-Auth-Token": self.auth_token, - "ACCEPT": "application/xml"}) - - body = etree.fromstring(content) - desc = body.find("{http://docs.openstack.org/identity/api/v2.0}description") - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(200, int(resp['status'])) - self.assertEqual(str(self.global_group), str(body.get('id'))) - self.assertEqual('A NEW description...', desc.text) - - def test_update_global_group_bad(self): - header = httplib2.Http(".cache") - resp_new, content_new = utils.create_global_group(self.global_group, - str(self.auth_token)) - url = '%sgroups/%s' % (utils.URL, self.global_group) - data = '{"group": { "description_bad": "A NEW description...", \ - "id":"%s" }}'\ - % (self.global_group) - #test for Content-Type = application/json - resp, content = header.request(url, "PUT", body=data, - headers={"Content-Type": "application/json", - "X-Auth-Token": self.auth_token}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(400, int(resp['status'])) - - def test_update_global_group_bad_xml(self): - header = httplib2.Http(".cache") - utils.create_global_group_xml(self.global_group, str(self.auth_token)) - url = '%sgroups/%s' % (utils.URL, self.global_group) - data = ' \ - A NEW description... \ - ' % (self.global_group) - #test for Content-Type = application/json - resp, content = header.request(url, "PUT", body=data, - headers={"Content-Type": "application/xml", - "X-Auth-Token": self.auth_token, - "ACCEPT": "application/xml"}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - - self.assertEqual(400, int(resp['status'])) - - def test_update_global_group_not_found(self): - header = httplib2.Http(".cache") - utils.create_global_group(self.global_group, str(self.auth_token)) - url = '%sgroups/NonexistingID' % (utils.URL) - data = '{"group": { "description": "A NEW description...", \ - "id":"NonexistingID"}}' - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body=data, - headers={"Content-Type": "application/json", - "X-Auth-Token": self.auth_token}) - self.assertEqual(404, int(resp['status'])) - - def test_update_global_group_not_found_xml(self): - header = httplib2.Http(".cache") - utils.create_tenant_xml(self.globaltenant, str(self.auth_token)) - url = '%sgroups/NonexistingID' % (utils.URL) - data = ' \ - \ - A NEW description... \ - ' - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body=data, - headers={"Content-Type": "application/xml", - "X-Auth-Token": self.auth_token, - "ACCEPT": "application/xml"}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(404, int(resp['status'])) - - -class DeleteGlobalGroupTest(GlobalGroupTest): - - def test_delete_global_group_not_found(self): - resp, content = utils.delete_global_group("test_global_group_1", - str(self.auth_token)) - self.assertEqual(404, int(resp['status'])) - - def test_delete_global_group_not_found_xml(self): - resp, content = utils.delete_global_group_xml("test_global_group_1", - str(self.auth_token)) - self.assertEqual(404, int(resp['status'])) - - def test_delete_global_group(self): - utils.create_tenant(self.globaltenant, str(self.auth_token)) - utils.create_tenant_group('test_global_group_delete', - self.globaltenant, str(self.auth_token)) - resp_new, content_new = utils.delete_global_group(\ - 'test_global_group_delete', - str(self.auth_token)) - resp = utils.delete_tenant(self.globaltenant, str(self.auth_token)) - self.assertEqual(204, int(resp_new['status'])) - - def test_delete_global_group_xml(self): - - utils.create_tenant_xml(self.globaltenant, str(self.auth_token)) - - utils.create_tenant_group_xml('test_global_group_delete', - self.globaltenant, str(self.auth_token)) - - resp_new, content_new = utils.delete_global_group_xml(\ - 'test_global_group_delete', - str(self.auth_token)) - utils.delete_tenant_xml(self.globaltenant, str(self.auth_token)) - - self.assertEqual(204, int(resp_new['status'])) - - -class AddUserGlobalGroupTest(unittest.TestCase): - - def setUp(self): - self.tenant = utils.get_global_tenant() - self.auth_token = utils.get_auth_token() - self.user = utils.get_user() - self.userdisabled = utils.get_userdisabled() - self.exp_auth_token = utils.get_exp_auth_token() - self.disabled_token = utils.get_disabled_token() - self.global_group = 'test_global_group' - utils.create_tenant(self.tenant, str(self.auth_token)) - utils.create_user(self.tenant, self.user, self.auth_token) - utils.add_user_json(self.tenant, self.user, self.auth_token) - self.token = utils.get_token(self.user, 'secrete', self.tenant, - 'token') - - def tearDown(self): - utils.delete_user_global_group(self.global_group, self.user, - str(self.auth_token)) - - utils.delete_user(self.tenant, self.user, str(self.auth_token)) - utils.delete_user(self.tenant, self.user, self.auth_token) - utils.delete_global_group(self.global_group, self.auth_token) - - def test_add_user_global_group(self): - resp, content = utils.create_global_group(self.global_group, - str(self.auth_token)) - utils.create_user(self.tenant, self.user, str(self.auth_token)) - resp_new, content_new = utils.add_user_global_group(self.global_group, - self.user, - str(self.auth_token)) - - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - if int(resp_new['status']) not in (200, 201): - self.fail('Failed due to %d' % int(resp_new['status'])) - - def test_add_user_global_group_xml(self): - resp, content = utils.create_global_group(self.global_group, - str(self.auth_token)) - utils.create_user(self.tenant, self.user, str(self.auth_token)) - resp_new, content_new = utils.add_user_global_group_xml(\ - self.global_group, - self.user, - str(self.auth_token)) - - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - if int(resp_new['status']) not in (200, 201): - self.fail('Failed due to %d' % int(resp_new['status'])) - - def test_add_user_global_group_conflict(self): - resp, content = utils.create_global_group(self.global_group, - str(self.auth_token)) - utils.create_user(self.tenant, self.user, str(self.auth_token)) - utils.add_user_global_group(self.global_group, self.user, - str(self.auth_token)) - resp_new, content_new = utils.add_user_global_group(self.global_group, - self.user, - str(self.auth_token)) - - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(409, int(resp_new['status'])) - - def test_add_user_global_group_conflict_xml(self): - resp, content = utils.create_global_group(self.global_group, - str(self.auth_token)) - utils.create_user(self.tenant, self.user, str(self.auth_token)) - utils.add_user_global_group_xml(self.global_group, self.user, - str(self.auth_token)) - resp_new, content_new = utils.add_user_global_group_xml(\ - self.global_group, - self.user, - str(self.auth_token)) - - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(409, int(resp_new['status'])) - - def test_add_user_global_group_unauthorized(self): - resp, content = utils.create_global_group(self.global_group, - str(self.auth_token)) - - utils.create_user(self.tenant, self.user, str(self.auth_token)) - - resp_new, content_new = utils.add_user_global_group(self.global_group, - self.user, - str(self.token)) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(401, int(resp_new['status'])) - - def test_add_user_global_group_unauthorized_xml(self): - resp, content = utils.create_global_group(self.global_group, - str(self.auth_token)) - utils.create_user(self.tenant, self.user, str(self.auth_token)) - resp_new, content_new = utils.add_user_global_group_xml(\ - self.global_group, - self.user, - str(self.token)) - - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(401, int(resp_new['status'])) - - def test_add_user_global_group_forbidden(self): - resp, content = utils.create_global_group(self.global_group, - str(self.auth_token)) - utils.create_user(self.tenant, self.user, str(self.auth_token)) - resp_new, content_new = utils.add_user_global_group(\ - self.global_group, - self.user, - str(self.disabled_token)) - - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(403, int(resp_new['status'])) - - def test_add_user_global_group_forbidden_xml(self): - resp, content = utils.create_global_group(self.global_group, - str(self.auth_token)) - utils.create_user(self.tenant, self.user, str(self.auth_token)) - resp_new, content_new = utils.add_user_global_group_xml(\ - self.global_group, - self.user, - str(self.disabled_token)) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(403, int(resp_new['status'])) - - -class GetUsersTenantGroupTest(unittest.TestCase): - - def setUp(self): - self.tenant = utils.get_global_tenant() - self.user = utils.get_user() - self.userdisabled = utils.get_userdisabled() - self.auth_token = utils.get_auth_token() - self.exp_auth_token = utils.get_exp_auth_token() - self.disabled_token = utils.get_disabled_token() - self.global_group = 'test_global_group' - utils.create_tenant(self.tenant, str(self.auth_token)) - utils.create_user(self.tenant, self.user, self.auth_token) - utils.add_user_json(self.tenant, self.user, self.auth_token) - self.token = utils.get_token(self.user, 'secrete', self.tenant, - 'token') - - def tearDown(self): - utils.delete_user_global_group(self.global_group, self.user, - str(self.auth_token)) - utils.delete_user(self.tenant, self.user, str(self.auth_token)) - utils.delete_global_group(self.global_group, self.auth_token) - - def test_get_users_global_group(self): - resp, content = utils.create_global_group(self.global_group, - str(self.auth_token)) - utils.create_user(self.tenant, self.user, str(self.auth_token)) - utils.add_user_global_group(self.global_group, self.user, - str(self.auth_token)) - resp_new, content_new = utils.get_user_global_group(\ - self.global_group, - str(self.auth_token)) - - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(200, int(resp_new['status'])) - - def test_get_users_global_group_xml(self): - resp, content = utils.create_global_group(self.global_group, - str(self.auth_token)) - utils.create_user(self.tenant, self.user, str(self.auth_token)) - utils.add_user_global_group_xml(self.global_group, self.user, - str(self.auth_token)) - resp_new, content_new = utils.get_user_global_group_xml(\ - self.global_group, - str(self.auth_token)) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(200, int(resp_new['status'])) - - def test_get_users_global_group_unauthorized(self): - resp, content = utils.create_global_group(self.global_group, - str(self.auth_token)) - utils.create_user(self.tenant, self.user, str(self.auth_token)) - utils.add_user_global_group(self.global_group, self.user, - str(self.auth_token)) - - resp_new, content_new = utils.get_user_global_group(\ - self.global_group, - str(self.token)) - - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(401, int(resp_new['status'])) - - def test_get_users_global_group_unauthorized_xml(self): - resp, content = utils.create_global_group(self.global_group, - str(self.auth_token)) - utils.create_user(self.tenant, self.user, str(self.auth_token)) - utils.add_user_global_group(self.global_group, self.user, - str(self.auth_token)) - resp_new, content_new = utils.get_user_global_group_xml(\ - self.global_group, - str(self.token)) - - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(401, int(resp_new['status'])) - - def test_get_users_global_group_forbidden(self): - resp, content = utils.create_global_group(self.global_group, - str(self.auth_token)) - utils.create_user(self.tenant, self.user, str(self.auth_token)) - utils.add_user_global_group(self.global_group, self.user, - str(self.auth_token)) - resp_new, content_new = utils.get_user_global_group(\ - self.global_group, - str(self.disabled_token)) - - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(403, int(resp_new['status'])) - - def test_get_users_global_group_forbidden_xml(self): - resp, content = utils.create_global_group(self.global_group, - str(self.auth_token)) - utils.create_user(self.tenant, self.user, str(self.auth_token)) - utils.add_user_global_group(self.global_group, self.user, - str(self.auth_token)) - resp_new, content_new = utils.get_user_global_group_xml(\ - self.global_group, - str(self.disabled_token)) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(403, int(resp_new['status'])) - - def test_get_users_global_group_expired(self): - resp, content = utils.create_global_group(self.global_group, - str(self.auth_token)) - utils.create_user(self.tenant, self.user, str(self.auth_token)) - utils.add_user_global_group(self.global_group, self.user, - str(self.auth_token)) - resp_new, content_new = utils.get_user_global_group(\ - self.global_group, - str(self.exp_auth_token)) - - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(403, int(resp_new['status'])) - - def test_get_users_global_group_expired_xml(self): - resp, content = utils.create_global_group(self.global_group, - str(self.auth_token)) - utils.create_user(self.tenant, self.user, str(self.auth_token)) - utils.add_user_global_group(self.global_group, self.user, - str(self.auth_token)) - resp_new, content_new = utils.get_user_global_group_xml(\ - self.global_group, - str(self.exp_auth_token)) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(403, int(resp_new['status'])) - - -class DeleteUsersGlobalGroupTest(unittest.TestCase): - - def setUp(self): - self.tenant = utils.get_global_tenant() - self.user = utils.get_user() - self.userdisabled = utils.get_userdisabled() - self.auth_token = utils.get_auth_token() - self.exp_auth_token = utils.get_exp_auth_token() - self.disabled_token = utils.get_disabled_token() - self.global_group = 'test_global_group' - utils.create_tenant(self.tenant, str(self.auth_token)) - utils.create_user(self.tenant, self.user, self.auth_token) - utils.add_user_json(self.tenant, self.user, self.auth_token) - self.token = utils.get_token(self.user, 'secrete', self.tenant, - 'token') - - def tearDown(self): - utils.delete_user_global_group(self.global_group, self.user, - str(self.auth_token)) - - utils.delete_user(self.tenant, self.user, str(self.auth_token)) - utils.delete_global_group(self.global_group, self.auth_token) - - def test_delete_user_global_group(self): - resp, content = utils.create_global_group(self.global_group, - str(self.auth_token)) - utils.create_user(self.tenant, self.user, str(self.auth_token)) - utils.add_user_global_group(self.global_group, self.user, - str(self.auth_token)) - - resp_new, content_new = utils.delete_user_global_group(\ - self.global_group, - self.user, - str(self.auth_token)) - - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(204, int(resp_new['status'])) - - def test_delete_user_global_group_xml(self): - resp, content = utils.create_global_group(self.global_group, - str(self.auth_token)) - utils.create_user(self.tenant, self.user, str(self.auth_token)) - utils.add_user_global_group(self.global_group, self.user, - str(self.auth_token)) - resp_new, content_new = utils.delete_user_global_group_xml(\ - self.global_group, - self.user, - str(self.auth_token)) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(204, int(resp_new['status'])) - - def test_delete_user_global_group_notfound(self): - resp, content = utils.create_global_group(self.global_group, - str(self.auth_token)) - utils.create_user(self.tenant, self.user, str(self.auth_token)) - utils.add_user_global_group(self.global_group, self.user, - str(self.disabled_token)) - utils.delete_user_global_group(self.global_group, self.user, - str(self.auth_token)) - resp_new, content_new = utils.delete_user_global_group( - self.global_group, - self.user, - str(self.auth_token)) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(404, int(resp_new['status'])) - - def test_delete_user_global_group_notfound_xml(self): - resp, content = utils.create_global_group(self.global_group, - str(self.auth_token)) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - utils.create_user(self.tenant, self.user, str(self.auth_token)) - utils.add_user_global_group(self.global_group, self.user, - str(self.disabled_token)) - utils.delete_user_global_group(self.global_group, self.user, - str(self.auth_token)) - resp_new, content_new = utils.delete_user_global_group_xml(\ - self.global_group, self.user, - str(self.auth_token)) - self.assertEqual(404, int(resp_new['status'])) - -if __name__ == '__main__': - unittest.main() diff --git a/test/unit/test_keystone.py b/test/unit/test_keystone.py deleted file mode 100644 index 3b17d9b2..00000000 --- a/test/unit/test_keystone.py +++ /dev/null @@ -1,60 +0,0 @@ -import logging -from lxml import etree -import os -import unittest - -MODULE_EXTENSIONS = set('.py'.split()) -TEST_FILES = ['test_authentication.py', 'test_keystone.py', 'test_tenants.py', - 'test_common.py', 'test_users.py', 'test_tenant_groups.py', - 'test_token.py', 'test_version.py', 'test_groups.py'] - - -def unit_test_extractor(tup, path, filenames): - """Pull ``unittest.TestSuite``s from modules in path - if the path represents a valid Python package. Accumulate - results in `tup[1]`. - """ - package_path, suites = tup - logging.debug('Path: %s', path) - logging.debug('Filenames: %s', filenames) - relpath = os.path.relpath(path, package_path) - relpath_pieces = relpath.split(os.sep) - - if relpath_pieces[0] == '.': # Base directory. - relpath_pieces.pop(0) # Otherwise, screws up module name. - elif not any(os.path.exists(os.path.join(path, '__init__' + ext)) - for ext in MODULE_EXTENSIONS): - return # Not a package directory and not the base directory, reject. - - logging.info('Base: %s', '.'.join(relpath_pieces)) - for filename in filenames: - if filename not in TEST_FILES: - continue - base, ext = os.path.splitext(filename) - #if ext not in MODULE_EXTENSIONS : # Not a Python module. - # continue - logging.info('Module: %s', base) - module_name = '.'.join(relpath_pieces + [base]) - logging.info('Importing from %s', module_name) - module = __import__(module_name) - module_suites = unittest.defaultTestLoader.loadTestsFromModule(module) - logging.info('Got suites: %s', module_suites) - suites += module_suites - - -def get_test_suites(path): - """:return: Iterable of suites for the packages/modules - present under :param:`path`. - """ - logging.info('Base path: %s', package_path) - suites = [] - os.path.walk(package_path, unit_test_extractor, (package_path, suites)) - logging.info('Got suites: %s', suites) - return suites - -if __name__ == '__main__': - logging.basicConfig(level=logging.WARN) - package_path = os.path.dirname(os.path.abspath(__file__)) - suites = get_test_suites(package_path) - for suite in suites: - unittest.TextTestRunner(verbosity=1).run(suite) diff --git a/test/unit/test_roles.py b/test/unit/test_roles.py deleted file mode 100644 index 10b16d27..00000000 --- a/test/unit/test_roles.py +++ /dev/null @@ -1,682 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright (c) 2010-2011 OpenStack, LLC. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -import httplib2 -import json -from lxml import etree -import os -import sys -sys.path.append(os.path.abspath(os.path.join(os.path.abspath(__file__), - '..', '..', '..', '..', 'keystone'))) -import unittest - -import test_common as utils -from test_common import URL - -class RolesTest(unittest.TestCase): - def setUp(self): - self.tenant = utils.get_tenant() - self.password = utils.get_password() - self.email = utils.get_email() - self.user = utils.get_user() - self.userdisabled = utils.get_userdisabled() - self.auth_token = utils.get_auth_token() - self.exp_auth_token = utils.get_exp_auth_token() - self.disabled_token = utils.get_disabled_token() - self.missing_token = utils.get_none_token() - self.invalid_token = utils.get_non_existing_token() - utils.create_tenant(self.tenant, str(self.auth_token)) - utils.create_user(self.tenant, self.user, self.auth_token) - self.token = utils.get_token(self.user, 'secrete', self.tenant, - 'token') - - def tearDown(self): - utils.delete_user(self.tenant, self.user, self.auth_token) - utils.delete_tenant(self.tenant, self.auth_token) - -class GetRolesTest(RolesTest): - def test_get_roles(self): - header = httplib2.Http(".cache") - url = '%sroles' % (utils.URL) - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body='{}', - headers={"Content-Type": "application/json", - "X-Auth-Token": self.auth_token}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(200, int(resp['status'])) - - #verify content - obj = json.loads(content) - if not "roles" in obj: - raise self.fail("Expecting Roles") - roles = obj["roles"]["values"] - if len(roles) != 1: - self.fail("Roles not of required length.") - - role = roles[0] - if not "id" in role: - role_id = None - else: - role_id = role["id"] - if role_id != 'Admin': - self.fail("Not the expected Role") - - - def test_get_roles_xml(self): - header = httplib2.Http(".cache") - url = '%sroles' % (utils.URL) - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body='', - headers={"Content-Type": "application/xml", - "X-Auth-Token": self.auth_token, - "ACCEPT": "application/xml"}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(200, int(resp['status'])) - - # Validate Returned Content - dom = etree.Element("root") - dom.append(etree.fromstring(content)) - roles = dom.find("{http://docs.openstack.org/identity/api/v2.0}" \ - "roles") - if roles == None: - self.fail("Expecting Roles") - roles = roles.findall("{http://docs.openstack.org/identity/api/v2.0}" \ - "role") - if len(roles) != 1: - self.fail("Not the expected Role count") - for role in roles: - if role.get("id") != 'Admin': - self.fail("Not the expected Role") - - - def test_get_roles_exp_token(self): - header = httplib2.Http(".cache") - url = '%sroles' % (utils.URL) - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body='{}', - headers={"Content-Type": "application/json", - "X-Auth-Token": self.exp_auth_token}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(403, int(resp['status'])) - - def test_get_roles_exp_token_xml(self): - header = httplib2.Http(".cache") - url = '%stenants' % (utils.URL) - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body='', - headers={"Content-Type": "application/xml", - "X-Auth-Token": self.exp_auth_token, - "ACCEPT": "application/xml"}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(403, int(resp['status'])) - -class GetRoleTest(RolesTest): - - def test_get_role(self): - self.role = 'Admin' - header = httplib2.Http(".cache") - url = '%sroles/%s' % (utils.URL, self.role) - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body='{}', - headers={"Content-Type": "application/json", - "X-Auth-Token": self.auth_token}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(200, int(resp['status'])) - - #verify content - obj = json.loads(content) - if not "role" in obj: - raise fault.BadRequestFault("Expecting Role") - role = obj["role"] - if not "id" in role: - role_id = None - else: - role_id = role["id"] - if role_id != 'Admin': - self.fail("Not the expected Role") - - def test_get_role_xml(self): - self.role = 'Admin' - header = httplib2.Http(".cache") - url = '%sroles/%s' % (utils.URL, self.role) - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body='', - headers={"Content-Type": "application/xml", - "X-Auth-Token": self.auth_token, - "ACCEPT": "application/xml"}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(200, int(resp['status'])) - - #verify content - dom = etree.Element("root") - dom.append(etree.fromstring(content)) - role = dom.find("{http://docs.openstack.org/identity/api/v2.0}" \ - "role") - if role == None: - self.fail("Expecting Role") - role_id = role.get("id") - if role_id != 'Admin': - self.fail("Not the expected Role") - - def test_get_role_bad(self): - header = httplib2.Http(".cache") - url = '%sroles/%s' % (utils.URL, 'tenant_bad') - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body='', - headers={"Content-Type": "application/json", - "X-Auth-Token": self.auth_token}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(404, int(resp['status'])) - - def test_get_role_xml_bad(self): - header = httplib2.Http(".cache") - url = '%sroles/%s' % (utils.URL, 'tenant_bad') - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body='', - headers={"Content-Type": "application/json", - "X-Auth-Token": self.auth_token}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(404, int(resp['status'])) - - def test_get_role_expired_token(self): - self.role = 'Admin' - header = httplib2.Http(".cache") - url = '%sroles/%s' % (utils.URL, self.role) - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body='{}', - headers={"Content-Type": "application/json", - "X-Auth-Token": self.exp_auth_token}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(403, int(resp['status'])) - - def test_get_role_xml_using_expired_token(self): - self.role = 'Admin' - header = httplib2.Http(".cache") - url = '%sroles/%s' % (utils.URL, self.role) - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body='', - headers={"Content-Type": "application/xml", - "X-Auth-Token": self.exp_auth_token, - "ACCEPT": "application/xml"}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(403, int(resp['status'])) - - def test_get_role_using_disabled_token(self): - self.role = 'Admin' - header = httplib2.Http(".cache") - url = '%sroles/%s' % (utils.URL, self.role) - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body='{}', - headers={"Content-Type": "application/json", - "X-Auth-Token": self.disabled_token}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(403, int(resp['status'])) - - def test_get_role_xml_using_disabled_token(self): - self.role = 'Admin' - header = httplib2.Http(".cache") - url = '%sroles/%s' % (utils.URL, self.role) - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body='', - headers={"Content-Type": "application/xml", - "X-Auth-Token": self.disabled_token, - "ACCEPT": "application/xml"}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(403, int(resp['status'])) - - def test_get_role_using_missing_token(self): - self.role = 'Admin' - header = httplib2.Http(".cache") - url = '%sroles/%s' % (utils.URL, self.role) - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body='{}', - headers={"Content-Type": "application/json", - "X-Auth-Token": self.missing_token}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(401, int(resp['status'])) - - def test_get_role_xml_using_missing_token(self): - self.role = 'Admin' - header = httplib2.Http(".cache") - url = '%sroles/%s' % (utils.URL, self.role) - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body='', - headers={"Content-Type": "application/xml", - "X-Auth-Token": self.missing_token, - "ACCEPT": "application/xml"}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(401, int(resp['status'])) - - def test_get_role_using_invalid_token(self): - self.role = 'Admin' - header = httplib2.Http(".cache") - url = '%sroles/%s' % (utils.URL, self.role) - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body='{}', - headers={"Content-Type": "application/json", - "X-Auth-Token": self.invalid_token}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(404, int(resp['status'])) - - def test_get_role_xml_using_invalid_token(self): - self.role = 'Admin' - header = httplib2.Http(".cache") - url = '%sroles/%s' % (utils.URL, self.role) - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body='', - headers={"Content-Type": "application/xml", - "X-Auth-Token": self.invalid_token, - "ACCEPT": "application/xml"}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(404, int(resp['status'])) - - -class CreateRoleRefTest(RolesTest): - def test_role_ref_create_json(self): - utils.add_user_json(self.tenant, self.user, self.auth_token) - resp, content = utils.create_role_ref(self.user, 'Admin', self.tenant, - str(self.auth_token)) - resp_val = int(resp['status']) - self.assertEqual(201, resp_val) - - def test_role_ref_create_xml(self): - utils.add_user_json(self.tenant, self.user, self.auth_token) - resp, content = utils.create_role_ref_xml(self.user, 'Admin', self.tenant, - str(self.auth_token)) - resp_val = int(resp['status']) - self.assertEqual(201, resp_val) - - def test_role_ref_create_json_using_expired_token(self): - utils.add_user_json(self.tenant, self.user, self.auth_token) - resp, content = utils.create_role_ref(self.user, 'Admin', self.tenant, - str(self.exp_auth_token)) - resp_val = int(resp['status']) - self.assertEqual(403, resp_val) - - def test_role_ref_create_json_using_disabled_token(self): - utils.add_user_json(self.tenant, self.user, self.auth_token) - resp, content = utils.create_role_ref(self.user, 'Admin', self.tenant, - str(self.disabled_token)) - resp_val = int(resp['status']) - self.assertEqual(403, resp_val) - - def test_role_ref_create_json_using_missing_token(self): - utils.add_user_json(self.tenant, self.user, self.auth_token) - resp, content = utils.create_role_ref(self.user, 'Admin', self.tenant, - str(self.missing_token)) - resp_val = int(resp['status']) - self.assertEqual(401, resp_val) - - def test_role_ref_create_json_using_invalid_token(self): - utils.add_user_json(self.tenant, self.user, self.auth_token) - resp, content = utils.create_role_ref(self.user, 'Admin', self.tenant, - str(self.invalid_token)) - resp_val = int(resp['status']) - self.assertEqual(404, resp_val) - - -class GetRoleRefsTest(RolesTest): - def test_get_rolerefs(self): - header = httplib2.Http(".cache") - utils.add_user_json(self.tenant, self.user, self.auth_token) - resp, content = utils.create_role_ref(self.user, 'Admin', self.tenant, - str(self.auth_token)) - url = '%susers/%s/roleRefs' % (URL, self.user) - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body='{}', - headers={"Content-Type": "application/json", - "X-Auth-Token": str(self.auth_token)}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(200, int(resp['status'])) - - #verify content - obj = json.loads(content) - if not "roleRefs" in obj: - raise self.fail("Expecting RoleRefs") - - def test_get_rolerefs_xml(self): - header = httplib2.Http(".cache") - utils.add_user_json(self.tenant, self.user, self.auth_token) - resp, content = utils.create_role_ref(self.user, 'Admin', self.tenant, - str(self.auth_token)) - url = '%susers/%s/roleRefs' % (URL, self.user) - #test for Content-Type = application/xml - resp, content = header.request(url, "GET", body='{}', - headers={"Content-Type": "application/xml", - "X-Auth-Token": str(self.auth_token), - "ACCEPT": "application/xml"}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(200, int(resp['status'])) - #verify content - dom = etree.Element("root") - dom.append(etree.fromstring(content)) - roles = dom.find("{http://docs.openstack.org/identity/api/v2.0}" \ - "roleRefs") - if roles == None: - self.fail("Expecting Role Refs") - - def test_get_rolerefs_using_expired_token(self): - header = httplib2.Http(".cache") - utils.add_user_json(self.tenant, self.user, self.auth_token) - resp, content = utils.create_role_ref(self.user, 'Admin', self.tenant, - str(self.auth_token)) - url = '%susers/%s/roleRefs' % (URL, self.user) - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body='{}', - headers={"Content-Type": "application/json", - "X-Auth-Token": str(self.exp_auth_token)}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(403, int(resp['status'])) - - def test_get_rolerefs_xml_using_expired_token(self): - header = httplib2.Http(".cache") - utils.add_user_json(self.tenant, self.user, self.auth_token) - resp, content = utils.create_role_ref(self.user, 'Admin', self.tenant, - str(self.auth_token)) - url = '%susers/%s/roleRefs' % (URL, self.user) - #test for Content-Type = application/xml - resp, content = header.request(url, "GET", body='{}', - headers={"Content-Type": "application/xml", - "X-Auth-Token": str(self.exp_auth_token), - "ACCEPT": "application/xml"}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(403, int(resp['status'])) - - def test_get_rolerefs_using_disabled_token(self): - header = httplib2.Http(".cache") - utils.add_user_json(self.tenant, self.user, self.auth_token) - resp, content = utils.create_role_ref(self.user, 'Admin', self.tenant, - str(self.auth_token)) - url = '%susers/%s/roleRefs' % (URL, self.user) - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body='{}', - headers={"Content-Type": "application/json", - "X-Auth-Token": str(self.disabled_token)}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(403, int(resp['status'])) - - def test_get_rolerefs_xml_using_disabled_token(self): - header = httplib2.Http(".cache") - utils.add_user_json(self.tenant, self.user, self.auth_token) - resp, content = utils.create_role_ref(self.user, 'Admin', self.tenant, - str(self.auth_token)) - url = '%susers/%s/roleRefs' % (URL, self.user) - #test for Content-Type = application/xml - resp, content = header.request(url, "GET", body='{}', - headers={"Content-Type": "application/xml", - "X-Auth-Token": str(self.disabled_token), - "ACCEPT": "application/xml"}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(403, int(resp['status'])) - - def test_get_rolerefs_using_missing_token(self): - header = httplib2.Http(".cache") - utils.add_user_json(self.tenant, self.user, self.auth_token) - resp, content = utils.create_role_ref(self.user, 'Admin', self.tenant, - str(self.auth_token)) - url = '%susers/%s/roleRefs' % (URL, self.user) - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body='{}', - headers={"Content-Type": "application/json", - "X-Auth-Token": str(self.missing_token)}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(401, int(resp['status'])) - - def test_get_rolerefs_xml_using_missing_token(self): - header = httplib2.Http(".cache") - utils.add_user_json(self.tenant, self.user, self.auth_token) - resp, content = utils.create_role_ref(self.user, 'Admin', self.tenant, - str(self.auth_token)) - url = '%susers/%s/roleRefs' % (URL, self.user) - #test for Content-Type = application/xml - resp, content = header.request(url, "GET", body='{}', - headers={"Content-Type": "application/xml", - "X-Auth-Token": str(self.missing_token), - "ACCEPT": "application/xml"}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(401, int(resp['status'])) - - def test_get_rolerefs_using_invalid_token(self): - header = httplib2.Http(".cache") - utils.add_user_json(self.tenant, self.user, self.auth_token) - resp, content = utils.create_role_ref(self.user, 'Admin', self.tenant, - str(self.auth_token)) - url = '%susers/%s/roleRefs' % (URL, self.user) - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body='{}', - headers={"Content-Type": "application/json", - "X-Auth-Token": str(self.invalid_token)}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(404, int(resp['status'])) - - def test_get_rolerefs_xml_using_missing_token(self): - header = httplib2.Http(".cache") - utils.add_user_json(self.tenant, self.user, self.auth_token) - resp, content = utils.create_role_ref(self.user, 'Admin', self.tenant, - str(self.auth_token)) - url = '%susers/%s/roleRefs' % (URL, self.user) - #test for Content-Type = application/xml - resp, content = header.request(url, "GET", body='{}', - headers={"Content-Type": "application/xml", - "X-Auth-Token": str(self.invalid_token), - "ACCEPT": "application/xml"}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(404, int(resp['status'])) - - -class DeleteRoleRefTest(RolesTest): - def test_delete_roleref(self): - header = httplib2.Http(".cache") - utils.add_user_json(self.tenant, self.user, self.auth_token) - resp, content = utils.create_role_ref(self.user, 'Admin', self.tenant, - str(self.auth_token)) - resp_val = int(resp['status']) - self.assertEqual(201, resp_val) - obj = json.loads(content) - if not "roleRef" in obj: - raise fault.BadRequestFault("Expecting RoleRef") - roleRef = obj["roleRef"] - if not "id" in roleRef: - role_ref_id = None - else: - role_ref_id = roleRef["id"] - if role_ref_id is None: - raise fault.BadRequestFault("Expecting RoleRefId") - url = '%susers/%s/roleRefs/%s' % (URL, self.user, role_ref_id) - resp, content = header.request(url, "DELETE", body='', - headers={"Content-Type": "application/json", - "X-Auth-Token": str(self.auth_token)}) - resp_val = int(resp['status']) - self.assertEqual(204, resp_val) - - def test_delete_roleref_using_expired_token(self): - header = httplib2.Http(".cache") - utils.add_user_json(self.tenant, self.user, self.auth_token) - resp, content = utils.create_role_ref(self.user, 'Admin', self.tenant, - str(self.auth_token)) - resp_val = int(resp['status']) - self.assertEqual(201, resp_val) - obj = json.loads(content) - if not "roleRef" in obj: - raise fault.BadRequestFault("Expecting RoleRef") - roleRef = obj["roleRef"] - if not "id" in roleRef: - role_ref_id = None - else: - role_ref_id = roleRef["id"] - if role_ref_id is None: - raise fault.BadRequestFault("Expecting RoleRefId") - url = '%susers/%s/roleRefs/%s' % (URL, self.user, role_ref_id) - resp, content = header.request(url, "DELETE", body='', - headers={"Content-Type": "application/json", - "X-Auth-Token": str(self.exp_auth_token)}) - resp_val = int(resp['status']) - self.assertEqual(403, resp_val) - - def test_delete_roleref_using_disabled_token(self): - header = httplib2.Http(".cache") - utils.add_user_json(self.tenant, self.user, self.auth_token) - resp, content = utils.create_role_ref(self.user, 'Admin', self.tenant, - str(self.auth_token)) - resp_val = int(resp['status']) - self.assertEqual(201, resp_val) - obj = json.loads(content) - if not "roleRef" in obj: - raise fault.BadRequestFault("Expecting RoleRef") - roleRef = obj["roleRef"] - if not "id" in roleRef: - role_ref_id = None - else: - role_ref_id = roleRef["id"] - if role_ref_id is None: - raise fault.BadRequestFault("Expecting RoleRefId") - url = '%susers/%s/roleRefs/%s' % (URL, self.user, role_ref_id) - resp, content = header.request(url, "DELETE", body='', - headers={"Content-Type": "application/json", - "X-Auth-Token": str(self.disabled_token)}) - resp_val = int(resp['status']) - self.assertEqual(403, resp_val) - - def test_delete_roleref_using_missing_token(self): - header = httplib2.Http(".cache") - utils.add_user_json(self.tenant, self.user, self.auth_token) - resp, content = utils.create_role_ref(self.user, 'Admin', self.tenant, - str(self.auth_token)) - resp_val = int(resp['status']) - self.assertEqual(201, resp_val) - obj = json.loads(content) - if not "roleRef" in obj: - raise fault.BadRequestFault("Expecting RoleRef") - roleRef = obj["roleRef"] - if not "id" in roleRef: - role_ref_id = None - else: - role_ref_id = roleRef["id"] - if role_ref_id is None: - raise fault.BadRequestFault("Expecting RoleRefId") - url = '%susers/%s/roleRefs/%s' % (URL, self.user, role_ref_id) - resp, content = header.request(url, "DELETE", body='', - headers={"Content-Type": "application/json", - "X-Auth-Token": str(self.missing_token)}) - resp_val = int(resp['status']) - self.assertEqual(401, resp_val) - - def test_delete_roleref_using_invalid_token(self): - header = httplib2.Http(".cache") - utils.add_user_json(self.tenant, self.user, self.auth_token) - resp, content = utils.create_role_ref(self.user, 'Admin', self.tenant, - str(self.auth_token)) - resp_val = int(resp['status']) - self.assertEqual(201, resp_val) - obj = json.loads(content) - if not "roleRef" in obj: - raise fault.BadRequestFault("Expecting RoleRef") - roleRef = obj["roleRef"] - if not "id" in roleRef: - role_ref_id = None - else: - role_ref_id = roleRef["id"] - if role_ref_id is None: - raise fault.BadRequestFault("Expecting RoleRefId") - url = '%susers/%s/roleRefs/%s' % (URL, self.user, role_ref_id) - resp, content = header.request(url, "DELETE", body='', - headers={"Content-Type": "application/json", - "X-Auth-Token": str(self.invalid_token)}) - resp_val = int(resp['status']) - self.assertEqual(404, resp_val) - - -if __name__ == '__main__': - unittest.main() diff --git a/test/unit/test_server.py b/test/unit/test_server.py deleted file mode 100644 index 294b1e54..00000000 --- a/test/unit/test_server.py +++ /dev/null @@ -1,86 +0,0 @@ -import unittest -import os -import sys -import json - -sys.path.append(os.path.abspath(os.path.join(os.path.abspath(__file__), - '..', '..', '..', '..', 'keystone'))) - -from keystone import server -import keystone.logic.types.auth as auth -import keystone.logic.types.fault as fault - -from StringIO import StringIO -from datetime import date -from lxml import etree -from webob import Request -from webob import Response - -class TestServer(unittest.TestCase): - '''Unit tests for server.py.''' - - request = None - auth_data = None - - def setUp(self): - environ = {'wsgi.url_scheme': 'http'} - self.request = Request(environ) - self.auth_data = auth.AuthData(auth.Token(date.today(),"2231312"), auth.User("username","12345",auth.Groups([],[]))) - - #def tearDown(self): - - def test_is_xml_response(self): - self.assertFalse(server.is_xml_response(self.request)) - self.request.headers["Accept"] = "application/xml" - self.request.content_type="application/json" - self.assertTrue(server.is_xml_response(self.request)) - - def test_send_result_xml(self): - self.request.headers["Accept"] = "application/xml" - response = server.send_result(200,self.request,self.auth_data); - - self.assertTrue(response.headers['content-type'] == "application/xml; charset=UTF-8") - xml = etree.fromstring(response.unicode_body) - - user = xml.find("{http://docs.openstack.org/identity/api/v2.0}user") - token = xml.find("{http://docs.openstack.org/identity/api/v2.0}token") - - self.assertTrue(user.get("username"),"username") - self.assertTrue(user.get("tenantId"),'12345'); - self.assertTrue(token.get("id"),'2231312'); - self.assertTrue(token.get("expires"),date.today()); - - def test_send_result_json(self): - self.request.headers["Accept"] = "application/json" - response = server.send_result(200,self.request,self.auth_data); - self.assertTrue(response.headers['content-type'] == "application/json; charset=UTF-8") - dict = json.loads(response.unicode_body) - self.assertTrue(dict['auth']['user']['username'],'username'); - self.assertTrue(dict['auth']['user']['tenantId'],'12345'); - self.assertTrue(dict['auth']['token']['id'],'2231312'); - self.assertTrue(dict['auth']['token']['expires'],date.today()); - - def test_get_auth_token(self): - self.request.headers["X-Auth-Token"]="Test token" - self.assertTrue(server.get_auth_token(self.request),"Test Token") - - def test_get_normalized_request_content_exception(self): - self.assertRaises(fault.IdentityFault,server.get_normalized_request_content,None,self.request) - - def test_get_normalized_request_content_xml(self): - self.request.environ["CONTENT_TYPE"]="application/xml" - pwd_cred = auth.PasswordCredentials("username","password","1") - body = ' \ - ' - str=StringIO() - str.write(body) - self.request.environ["wsgi.input"]=str - self.request.environ["CONTENT_LENGTH"] = str.len - #TODO: I THINK THIS belongs in a test for auth.py. - - -if __name__ == '__main__': - unittest.main() \ No newline at end of file diff --git a/test/unit/test_tenant_groups.py b/test/unit/test_tenant_groups.py deleted file mode 100644 index 21bb9221..00000000 --- a/test/unit/test_tenant_groups.py +++ /dev/null @@ -1,1217 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright (c) 2010-2011 OpenStack, LLC. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -import httplib2 -import json -from lxml import etree -import os -import sys -sys.path.append(os.path.abspath(os.path.join(os.path.abspath(__file__), - '..', '..', '..', '..', 'keystone'))) -import unittest - -import test_common as util - - -class TenantGroupTest(unittest.TestCase): - - def setUp(self): - self.tenant = util.get_another_tenant() - self.user = util.get_user() - self.userdisabled = util.get_userdisabled() - self.auth_token = util.get_auth_token() - self.exp_auth_token = util.get_exp_auth_token() - self.disabled_token = util.get_disabled_token() - self.tenant_group = 'test_tenant_group_new' - util.create_tenant(self.tenant, str(self.auth_token)) - util.create_user(self.tenant, self.user, self.auth_token) - util.add_user_json(self.tenant, self.user, self.auth_token) - self.token = util.get_token(self.user, 'secrete', self.tenant, - 'token') - - def tearDown(self): - resp = util.delete_user(self.tenant, self.user, - str(self.auth_token)) - - resp, content = util.delete_tenant_group(self.tenant_group, - self.tenant, - self.auth_token) - resp = util.delete_tenant(self.tenant, self.auth_token) - - -class CreateTenantGroupTest(TenantGroupTest): - - def test_tenant_group_create(self): - util.delete_user(self.tenant, self.user, - str(self.auth_token)) - resp = util.delete_tenant(self.tenant, str(self.auth_token)) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - util.create_tenant(self.tenant, str(self.auth_token)) - resp, content = util.delete_tenant_group(self.tenant_group, - self.tenant, - str(self.auth_token)) - resp, content = util.create_tenant_group(self.tenant_group, - self.tenant, - str(self.auth_token)) - - if int(resp['status']) not in (200, 201): - self.fail('Failed due to %d' % int(resp['status'])) - - def test_tenant_group_create_xml(self): - util.delete_user(self.tenant, self.user, - str(self.auth_token)) - resp = util.delete_tenant_xml(self.tenant, - str(self.auth_token)) - resp, content = util.create_tenant_xml(self.tenant, - str(self.auth_token)) - resp, content = util.delete_tenant_group_xml(self.tenant_group, - self.tenant, - str(self.auth_token)) - resp, content = util.create_tenant_group_xml(self.tenant_group, - self.tenant, - str(self.auth_token)) - - content = etree.fromstring(content) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - if int(resp['status']) not in (200, 201): - self.fail('Failed due to %d' % int(resp['status'])) - - def test_tenant_group_create_again(self): - resp, content = util.create_tenant(self.tenant, - str(self.auth_token)) - resp, content = util.create_tenant_group(self.tenant_group, - self.tenant, - str(self.auth_token)) - resp, content = util.create_tenant_group(self.tenant_group, - self.tenant, - str(self.auth_token)) - if int(resp['status']) == 200: - self.tenant = content['tenant']['id'] - self.tenant_group = content['group']['id'] - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(409, int(resp['status'])) - - def test_tenant_group_create_again_xml(self): - resp, content = util.create_tenant_xml("test_tenant", - str(self.auth_token)) - resp, content = util.create_tenant_group_xml(self.tenant_group, - self.tenant, - str(self.auth_token)) - resp_new, content_new = util.create_tenant_group_xml(self.tenant_group, - self.tenant, - str(self.auth_token)) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(409, int(resp['status'])) - - def test_tenant_group_create_unauthorized_token(self): - header = httplib2.Http(".cache") - resp, content = util.create_tenant(self.tenant, str(self.auth_token)) - if int(resp['status']) == 200: - self.tenant = content['tenant']['id'] - resp, content = util.create_tenant_group_xml(self.tenant_group, - self.tenant, - str(self.auth_token)) - - if int(resp['status']) == 200: - self.tenant_group = resp['group']['id'] - url = '%stenants/%s/groups' % (util.URL, self.tenant) - body = {"group": {"id": self.tenant_group, - "description": "A description ..."}} - resp, content = header.request(url, "POST", body=json.dumps(body), - headers={"Content-Type": "application/json", - "X-Auth-Token": self.token}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(401, int(resp['status'])) - - def test_tenant_group_create_unauthorized_token_xml(self): - header = httplib2.Http(".cache") - resp, content = util.create_tenant(self.tenant, str(self.auth_token)) - if int(resp['status']) == 200: - self.tenant = content['tenant']['id'] - url = '%stenants/%s/groups' % (util.URL, self.tenant) - body = ' \ - A description... \ - ' % self.tenant_group - resp, content = header.request(url, "POST", body=body, - headers={"Content-Type": "application/xml", - "X-Auth-Token": self.token, - "ACCEPT": "application/xml"}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(401, int(resp['status'])) - - def test_tenant_group_create_expired_token(self): - header = httplib2.Http(".cache") - resp, content = util.create_tenant(self.tenant, str(self.auth_token)) - if int(resp['status']) == 200: - self.tenant = content['tenant']['id'] - url = '%stenants/%s/groups' % (util.URL, self.tenant) - body = {"group": {"id": self.tenant_group, - "description": "A description ..."}} - resp, content = header.request(url, "POST", body=json.dumps(body), - headers={"Content-Type": "application/json", - "X-Auth-Token": self.exp_auth_token}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(403, int(resp['status'])) - - def test_tenant_group_create_expired_token_xml(self): - header = httplib2.Http(".cache") - resp, content = util.create_tenant_xml(self.tenant, - str(self.auth_token)) - content = etree.fromstring(content) - if int(resp['status']) == 200: - self.tenant = content.get('id') - url = '%stenants/%s/groups' % (util.URL, self.tenant) - body = ' \ - \ - A description... \ - ' % self.tenant - resp, content = header.request(url, "POST", body=body, - headers={"Content-Type": "application/xml", - "X-Auth-Token": self.exp_auth_token, - "ACCEPT": "application/xml"}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(403, int(resp['status'])) - - def test_tenant_group_create_missing_token(self): - header = httplib2.Http(".cache") - resp, content = util.create_tenant(self.tenant, str(self.auth_token)) - if int(resp['status']) == 200: - self.tenant = content['tenant']['id'] - url = '%stenants/%s/groups' % (util.URL, self.tenant) - body = {"group": {"id": self.tenant_group, - "description": "A description ..."}} - resp, content = header.request(url, "POST", body=json.dumps(body), - headers={"Content-Type": "application/json"}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(401, int(resp['status'])) - - def test_tenant_group_create_missing_token_xml(self): - header = httplib2.Http(".cache") - resp, content = util.create_tenant_xml(self.tenant, - str(self.auth_token)) - content = etree.fromstring(content) - if int(resp['status']) == 200: - self.tenant = content.get('id') - url = '%stenants/%s/groups' % (util.URL, self.tenant) - body = ' \ - \ - A description... \ - ' % self.tenant_group - resp, content = header.request(url, "POST", body=body, - headers={"Content-Type": "application/xml", - "ACCEPT": "application/xml"}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(401, int(resp['status'])) - - def test_tenant_group_create_disabled_token(self): - header = httplib2.Http(".cache") - resp, content = util.create_tenant(self.tenant, str(self.auth_token)) - if int(resp['status']) == 200: - self.tenant = content['tenant']['id'] - - url = '%stenants/%s/groups' % (util.URL, self.tenant) - body = '{"group": { "id": "%s", \ - "description": "A description ..." } }' % self.tenant_group - resp, content = header.request(url, "POST", body=body, - headers={"Content-Type": "application/json", - "X-Auth-Token": self.disabled_token}) - - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(403, int(resp['status'])) - - def test_tenant_group_create_disabled_token_xml(self): - header = httplib2.Http(".cache") - resp, content = util.create_tenant_xml(self.tenant, - str(self.auth_token)) - content = etree.fromstring(content) - if int(resp['status']) == 200: - self.tenant = content.get('id') - - url = '%stenants/%s/groups' % (util.URL, self.tenant) - body = ' \ - \ - A description... \ - ' % self.tenant_group - resp, content = header.request(url, "POST", body=body, - headers={"Content-Type": "application/xml", - "X-Auth-Token": self.disabled_token, - "ACCEPT": "application/xml"}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(403, int(resp['status'])) - - def test_tenant_group_create_invalid_token(self): - header = httplib2.Http(".cache") - resp, content = util.create_tenant(self.tenant, str(self.auth_token)) - if int(resp['status']) == 200: - self.tenant = content['tenant']['id'] - - url = '%stenants/%s/groups' % (util.URL, self.tenant) - body = '{"group": { "id": "%s", \ - "description": "A description ..." } }' % self.tenant - resp, content = header.request(url, "POST", body=body, - headers={"Content-Type": "application/json", - "X-Auth-Token": 'nonexsitingtoken'}) - - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(404, int(resp['status'])) - - def test_tenant_group_create_invalid_token_xml(self): - header = httplib2.Http(".cache") - resp, content = util.create_tenant_xml(self.tenant, - str(self.auth_token)) - content = etree.fromstring(content) - if int(resp['status']) == 200: - self.tenant = content.get('id') - - url = '%stenants/%s/groups' % (util.URL, self.tenant) - body = ' \ - \ - A description... \ - ' % self.tenant_group - resp, content = header.request(url, "POST", body=body, - headers={"Content-Type": "application/xml", - "X-Auth-Token": 'nonexsitingtoken', - "ACCEPT": "application/xml"}) - - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(404, int(resp['status'])) - - -class GetTenantGroupsTest(TenantGroupTest): - - def test_get_tenant_groups(self): - header = httplib2.Http(".cache") - resp, content = util.create_tenant(self.tenant, str(self.auth_token)) - - resp, content = util.create_tenant_group(self.tenant_group, - self.tenant, - str(self.auth_token)) - - url = '%stenants/%s/groups' % (util.URL, self.tenant) - - resp, content = header.request(url, "GET", body='{}', - headers={"Content-Type": "application/json", - "X-Auth-Token": self.auth_token}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(200, int(resp['status'])) - - def test_get_tenant_groups_xml(self): - header = httplib2.Http(".cache") - resp, content = util.create_tenant(self.tenant, str(self.auth_token)) - - resp, content = util.create_tenant_group_xml(self.tenant_group, - self.tenant, - str(self.auth_token)) - url = '%stenants/%s/groups' % (util.URL, self.tenant) - resp, content = header.request(url, "GET", body='', - headers={"Content-Type": "application/xml", - "X-Auth-Token": self.auth_token, - "ACCEPT": "application/xml"}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(200, int(resp['status'])) - - def test_get_tenant_groups_unauthorized_token(self): - header = httplib2.Http(".cache") - resp, content = util.create_tenant(self.tenant, str(self.auth_token)) - - resp, content = util.create_tenant_group(self.tenant_group, - self.tenant, - str(self.auth_token)) - url = '%stenants/%s/groups' % (util.URL, self.tenant) - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body='{}', - headers={"Content-Type": "application/json", - "X-Auth-Token": self.token}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(401, int(resp['status'])) - - def test_get_tenant_groups_unauthorized_token_xml(self): - header = httplib2.Http(".cache") - resp, content = util.create_tenant(self.tenant, str(self.auth_token)) - resp, content = util.create_tenant_group(self.tenant_group, - self.tenant, - str(self.auth_token)) - url = '%stenants/%s/groups' % (util.URL, self.tenant) - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body='', - headers={"Content-Type": "application/xml", - "X-Auth-Token": self.token, - "ACCEPT": "application/xml"}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(401, int(resp['status'])) - - def test_get_tenant_groups_exp_token(self): - header = httplib2.Http(".cache") - resp, content = util.create_tenant(self.tenant, str(self.auth_token)) - resp, content = util.create_tenant_group(self.tenant_group, - self.tenant, - str(self.auth_token)) - url = '%stenants/%s/groups' % (util.URL, self.tenant) - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body='{}', - headers={"Content-Type": "application/json", - "X-Auth-Token": self.exp_auth_token}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(403, int(resp['status'])) - - def test_get_tenant_groups_exp_token_xml(self): - header = httplib2.Http(".cache") - resp, content = util.create_tenant(self.tenant, str(self.auth_token)) - resp, content = util.create_tenant_group(self.tenant_group, - self.tenant, - str(self.auth_token)) - url = '%stenants/%s/groups' % (util.URL, self.tenant) - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body='', - headers={"Content-Type": "application/xml", - "X-Auth-Token": self.exp_auth_token, - "ACCEPT": "application/xml"}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(403, int(resp['status'])) - - -class GetTenantGroupTest(TenantGroupTest): - - def test_get_tenant_group(self): - header = httplib2.Http(".cache") - resp, content = util.create_tenant(self.tenant, str(self.auth_token)) - resp, content = util.create_tenant_group(self.tenant_group, - self.tenant, - str(self.auth_token)) - url = '%stenants/%s/groups/%s' % (util.URL, self.tenant, - self.tenant_group) - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body='{}', - headers={"Content-Type": "application/json", - "X-Auth-Token": self.auth_token}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(200, int(resp['status'])) - - def test_get_tenant_group_xml(self): - header = httplib2.Http(".cache") - resp, content = util.create_tenant(self.tenant, str(self.auth_token)) - resp, content = util.create_tenant_group(self.tenant_group, - self.tenant, - str(self.auth_token)) - url = '%stenants/%s/groups/%s' % (util.URL, self.tenant, - self.tenant_group) - #test for Content-Type = application/xml - resp, content = header.request(url, "GET", body='', - headers={"Content-Type": "application/xml", - "X-Auth-Token": self.auth_token, - "ACCEPT": "application/xml"}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(200, int(resp['status'])) - - def test_get_tenant_group_bad(self): - header = httplib2.Http(".cache") - resp, content = util.create_tenant(self.tenant, str(self.auth_token)) - resp, content = util.create_tenant_group(self.tenant_group, - self.tenant, - str(self.auth_token)) - url = '%stenants/%s/groups/%s' % (util.URL, 'tenant_bad', - self.tenant_group) - - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body='{', - headers={"Content-Type": "application/json", - "X-Auth-Token": self.auth_token}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(404, int(resp['status'])) - - def test_get_tenant_group_bad_xml(self): - header = httplib2.Http(".cache") - resp, content = util.create_tenant(self.tenant, str(self.auth_token)) - resp, content = util.create_tenant_group(self.tenant_group, - self.tenant, - str(self.auth_token)) - url = '%stenants/%s/groups/%s' % (util.URL, 'tenant_bad', - self.tenant_group) - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body='{', - headers={"Content-Type": "application/xml", - "X-Auth-Token": self.auth_token, - "ACCEPT": "application/xml"}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(404, int(resp['status'])) - - def test_get_tenant_group_not_found(self): - header = httplib2.Http(".cache") - resp, content = util.create_tenant(self.tenant, str(self.auth_token)) - resp, content = util.create_tenant_group(self.tenant_group, - self.tenant, - str(self.auth_token)) - url = '%stenants/%s/groups/%s' % (util.URL, self.tenant, - 'nonexistinggroup') - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body='{}', - headers={"Content-Type": "application/json", - "X-Auth-Token": self.auth_token}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(404, int(resp['status'])) - - def test_get_tenant_group_not_found_xml(self): - header = httplib2.Http(".cache") - resp, content = util.create_tenant(self.tenant, str(self.auth_token)) - resp, content = util.create_tenant_group(self.tenant_group, - self.tenant, - str(self.auth_token)) - url = '%stenants/%s/groups/%s' % (util.URL, self.tenant, - 'nonexistinggroup') - - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body='', - headers={"Content-Type": "application/xml", - "X-Auth-Token": self.auth_token, - "ACCEPT": "application/xml"}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(404, int(resp['status'])) - - -class UpdateTenantGroupTest(TenantGroupTest): - - def test_update_tenant_group(self): - header = httplib2.Http(".cache") - resp, content = util.create_tenant(self.tenant, str(self.auth_token)) - resp, content = util.delete_tenant_group(self.tenant_group, - self.tenant, - str(self.auth_token)) - resp, content = util.create_tenant_group(self.tenant_group, - self.tenant, - str(self.auth_token)) - url = '%stenants/%s/groups/%s' % (util.URL, self.tenant, - self.tenant_group) - - data = '{"group": { "id":"%s","description": "A NEW description..." ,\ - "tenantId":"%s" }}' % (self.tenant_group, self.tenant) - #test for Content-Type = application/json - - resp, content = header.request(url, "PUT", body=data, - headers={"Content-Type": "application/json", - "X-Auth-Token": self.auth_token}) - - body = json.loads(content) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(200, int(resp['status'])) - self.assertEqual(self.tenant_group, body['group']['id']) - self.assertEqual('A NEW description...', body['group']['description']) - - def test_update_tenant_group_xml(self): - header = httplib2.Http(".cache") - resp = util.delete_tenant(self.tenant, str(self.auth_token)) - - resp, content = util.create_tenant(self.tenant, str(self.auth_token)) - - resp, content = util.delete_tenant_group(self.tenant_group, - self.tenant, - str(self.auth_token)) - - resp, content = util.create_tenant_group(self.tenant_group, - self.tenant, - str(self.auth_token)) - - url = '%stenants/%s/groups/%s' % (util.URL, self.tenant, - self.tenant_group) - - data = ' \ - A NEW description... \ - ' % (self.tenant, self.tenant_group) - - #test for Content-Type = application/json - resp, content = header.request(url, "PUT", body=data, - headers={"Content-Type": "application/xml", - "X-Auth-Token": self.auth_token, - "ACCEPT": "application/xml"}) - - body = etree.fromstring(content) - desc = body.find("{http://docs.openstack.org/identity/api/v2.0}description") - - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - - self.assertEqual(200, int(resp['status'])) - self.assertEqual(str(self.tenant_group), str(body.get('id'))) - self.assertEqual('A NEW description...', desc.text) - - def test_update_tenant_group_bad(self): - header = httplib2.Http(".cache") - resp, content = util.create_tenant(self.tenant, str(self.auth_token)) - resp, content = util.delete_tenant_group(self.tenant_group, - self.tenant, - str(self.auth_token)) - resp, content = util.create_tenant_group(self.tenant_group, - self.tenant, - str(self.auth_token)) - url = '%stenants/%s/groups/%s' % (util.URL, self.tenant, - self.tenant_group) - data = '{"group": { "description_bad": "A NEW description...",\ - "id":"%s","tenantId":"%s" }}' % (self.tenant_group, self.tenant) - #test for Content-Type = application/json - - resp, content = header.request(url, "PUT", body=data, - headers={"Content-Type": "application/json", - "X-Auth-Token": self.auth_token}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(400, int(resp['status'])) - - def test_update_tenant_group_bad_xml(self): - header = httplib2.Http(".cache") - resp, content = util.create_tenant(self.tenant, str(self.auth_token)) - resp, content = util.delete_tenant_group(self.tenant_group, - self.tenant, - str(self.auth_token)) - resp, content = util.create_tenant_group(self.tenant_group, - self.tenant, - str(self.auth_token)) - url = '%stenants/%s/groups/%s' % (util.URL, self.tenant, - self.tenant_group) - data = ' \ - \ - A NEW description... \ - ' % (self.tenant, self.tenant_group) - #test for Content-Type = application/json - resp, content = header.request(url, "PUT", body=data, - headers={"Content-Type": "application/xml", - "X-Auth-Token": self.auth_token, - "ACCEPT": "application/xml"}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(400, int(resp['status'])) - - def test_update_tenant_group_not_found(self): - header = httplib2.Http(".cache") - resp, content = util.create_tenant(self.tenant, str(self.auth_token)) - resp, content = util.delete_tenant_group(self.tenant_group, - self.tenant, - str(self.auth_token)) - resp, content = util.create_tenant_group(self.tenant_group, - self.tenant, - str(self.auth_token)) - url = '%stenants/%s/groups/NonexistingID' % (util.URL, self.tenant) - - data = '{"group": { "description": "A NEW description...",\ - "id":"NonexistingID", "tenantId"="test_tenant" }}' - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body=data, - headers={"Content-Type": "application/json", - "X-Auth-Token": self.auth_token}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(404, int(resp['status'])) - - def test_update_tenant_group_not_found_xml(self): - header = httplib2.Http(".cache") - resp, content = util.create_tenant(self.tenant, str(self.auth_token)) - url = '%stenants/%s/groups/NonexistingID' % (util.URL, self.tenant) - data = ' \ - \ - A NEW description... \ - ' - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body=data, - headers={"Content-Type": "application/xml", - "X-Auth-Token": self.auth_token, - "ACCEPT": "application/xml"}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(404, int(resp['status'])) - - -class DeleteTenantGroupTest(TenantGroupTest): - - def test_delete_tenant_group_not_found(self): - resp, content = util.delete_tenant_group("test_tenant_delete111", - self.tenant, - str(self.auth_token)) - self.assertEqual(404, int(resp['status'])) - - def test_delete_tenant_group_not_found_xml(self): - resp, content = util.delete_tenant_group_xml("test_tenant_delete111", - self.tenant, - str(self.auth_token)) - self.assertEqual(404, int(resp['status'])) - - def test_delete_tenant_group(self): - resp, content = util.create_tenant("test_tenant_delete", - str(self.auth_token)) - resp, content = util.create_tenant_group(self.tenant_group, - 'test_tenant_delete', - str(self.auth_token)) - resp, content = util.delete_tenant_group(self.tenant_group, - 'test_tenant_delete', - str(self.auth_token)) - self.assertEqual(204, int(resp['status'])) - resp = util.delete_tenant("test_tenant_delete", - str(self.auth_token)) - self.assertEqual(204, int(resp['status'])) - - -class AddUserTenantGroupTest(TenantGroupTest): - - def setUp(self): - self.tenant = 'test_tenant' - self.user = util.get_user() - self.userdisabled = util.get_userdisabled() - self.auth_token = util.get_auth_token() - self.exp_auth_token = util.get_exp_auth_token() - self.disabled_token = util.get_disabled_token() - self.tenant_group = 'test_tenant_group_add' - util.create_tenant(self.tenant, str(self.auth_token)) - util.create_user(self.tenant, self.user, self.auth_token) - util.add_user_json(self.tenant, self.user, self.auth_token) - self.token = util.get_token(self.user, 'secrete', self.tenant, - 'token') - - def tearDown(self): - resp, content = util.delete_user_tenant_group(self.tenant, - self.tenant_group, - self.user, - str(self.auth_token)) - - resp = util.delete_user(self.tenant, self.user, - str(self.auth_token)) - resp, content = util.delete_tenant_group(self.tenant_group, - self.tenant, - self.auth_token) - resp = util.delete_tenant(self.tenant, self.auth_token) - - def test_add_user_tenant_group(self): - resp, content = util.create_tenant(self.tenant, str(self.auth_token)) - - resp, content = util.create_tenant_group(self.tenant_group, - self.tenant, - str(self.auth_token)) - - resp, content = util.create_user(self.tenant, self.user, - str(self.auth_token)) - resp, content = util.add_user_tenant_group(self.tenant, - self.tenant_group, - self.user, - str(self.auth_token)) - - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - if int(resp['status']) not in (200, 201): - self.fail('Failed due to %d' % int(resp['status'])) - - def test_add_user_tenant_group_xml(self): - resp, content = util.create_tenant(self.tenant, str(self.auth_token)) - resp, content = util.create_tenant_group(self.tenant_group, - self.tenant, - str(self.auth_token)) - resp, content = util.create_user(self.tenant, self.user, - str(self.auth_token)) - resp, content = util.add_user_tenant_group_xml(self.tenant, - self.tenant_group, - self.user, - str(self.auth_token)) - - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - if int(resp['status']) not in (200, 201): - self.fail('Failed due to %d' % int(resp['status'])) - - def test_add_user_tenant_group_conflict(self): - resp, content = util.create_tenant(self.tenant, str(self.auth_token)) - resp, content = util.create_tenant_group(self.tenant_group, - self.tenant, - str(self.auth_token)) - resp, content = util.create_user(self.tenant, self.user, - str(self.auth_token)) - resp, content = util.add_user_tenant_group(self.tenant, - self.tenant_group, - self.user, - str(self.auth_token)) - resp, content = util.add_user_tenant_group(self.tenant, - self.tenant_group, - self.user, - str(self.auth_token)) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(409, int(resp['status'])) - - def test_add_user_tenant_group_conflict_xml(self): - resp, content = util.create_tenant(self.tenant, str(self.auth_token)) - resp, content = util.create_tenant_group(self.tenant_group, - self.tenant, - str(self.auth_token)) - resp, content = util.create_user(self.tenant, self.user, - str(self.auth_token)) - resp, content = util.add_user_tenant_group_xml(self.tenant, - self.tenant_group, - self.user, str(self.auth_token)) - resp, content = util.add_user_tenant_group_xml(self.tenant, - self.tenant_group, - self.user, - str(self.auth_token)) - - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(409, int(resp['status'])) - - def test_add_user_tenant_group_unauthorized(self): - resp, content = util.create_tenant(self.tenant, str(self.auth_token)) - resp, content = util.create_tenant_group(self.tenant_group, - self.tenant, - str(self.auth_token)) - resp, content = util.create_user(self.tenant, self.user, - str(self.auth_token)) - - resp, content = util.add_user_tenant_group(self.tenant, - self.tenant_group, - self.user, self.token) - - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(401, int(resp['status'])) - - def test_add_user_tenant_group_unauthorized_xml(self): - resp, content = util.create_tenant(self.tenant, str(self.auth_token)) - resp, content = util.create_tenant_group(self.tenant_group, - self.tenant, - str(self.auth_token)) - resp, content = util.create_user(self.tenant, self.user, - str(self.auth_token)) - - resp, content = util.add_user_tenant_group_xml(self.tenant, - self.tenant_group, - self.user, self.token) - - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(401, int(resp['status'])) - - def test_add_user_tenant_group_forbidden(self): - resp, content = util.create_tenant(self.tenant, str(self.auth_token)) - resp, content = util.create_tenant_group(self.tenant_group, - self.tenant, - str(self.auth_token)) - resp, content = util.create_user(self.tenant, self.user, - str(self.auth_token)) - - resp, content = util.add_user_tenant_group(self.tenant, - self.tenant_group, - self.user, - self.disabled_token) - - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(403, int(resp['status'])) - - def test_add_user_tenant_group_forbidden_xml(self): - resp, content = util.create_tenant(self.tenant, str(self.auth_token)) - resp, content = util.create_tenant_group(self.tenant_group, - self.tenant, - str(self.auth_token)) - resp, content = util.create_user(self.tenant, self.user, - str(self.auth_token)) - - resp, content = util.add_user_tenant_group_xml(self.tenant, - self.tenant_group, - self.user, - self.disabled_token) - - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(403, int(resp['status'])) - - -class GetUsersTenantGroupTest(TenantGroupTest): - - def setUp(self): - self.tenant = 'test_tenant' - self.user = util.get_user() - self.userdisabled = util.get_userdisabled() - self.auth_token = util.get_auth_token() - self.exp_auth_token = util.get_exp_auth_token() - self.disabled_token = util.get_disabled_token() - self.tenant_group = 'test_tenant_group_add' - util.create_tenant(self.tenant, str(self.auth_token)) - util.create_user(self.tenant, self.user, self.auth_token) - util.add_user_json(self.tenant, self.user, self.auth_token) - self.token = util.get_token(self.user, 'secrete', self.tenant, - 'token') - - def tearDown(self): - resp, content = util.delete_user_tenant_group(self.tenant, - self.tenant_group, - self.user, - str(self.auth_token)) - - resp = util.delete_user(self.tenant, self.user, - str(self.auth_token)) - resp, content = util.delete_tenant_group(self.tenant_group, - self.tenant, - self.auth_token) - util.delete_tenant(self.tenant, self.auth_token) - - def test_get_users_tenant_group(self): - resp, content = util.create_tenant(self.tenant, str(self.auth_token)) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - resp, content = util.create_tenant_group(self.tenant_group, - self.tenant, - str(self.auth_token)) - - util.create_user(self.tenant, self.user, - str(self.auth_token)) - util.add_user_tenant_group(self.tenant, - self.tenant_group, - self.user, - str(self.auth_token)) - resp, content = util.get_user_tenant_group(self.tenant, - self.tenant_group, - str(self.auth_token)) - - self.assertEqual(200, int(resp['status'])) - - def test_get_users_tenant_group_xml(self): - resp, content = util.create_tenant(self.tenant, str(self.auth_token)) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - util.create_tenant_group(self.tenant_group, - self.tenant, - str(self.auth_token)) - util.create_user(self.tenant, self.user, - str(self.auth_token)) - util.add_user_tenant_group_xml(self.tenant, - self.tenant_group, - self.user, - str(self.auth_token)) - resp, content = util.get_user_tenant_group_xml(self.tenant, - self.tenant_group, - str(self.auth_token)) - - self.assertEqual(200, int(resp['status'])) - - def test_get_users_tenant_group_unauthorized(self): - resp, content = util.create_tenant(self.tenant, str(self.auth_token)) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - util.create_tenant_group(self.tenant_group, - self.tenant, - str(self.auth_token)) - util.create_user(self.tenant, self.user, - str(self.auth_token)) - - util.add_user_tenant_group(self.tenant, - self.tenant_group, - self.user, - self.auth_token) - - resp, content = util.get_user_tenant_group(self.tenant, - self.tenant_group, - str(self.token)) - self.assertEqual(401, int(resp['status'])) - - def test_get_users_tenant_group_unauthorized_xml(self): - resp, content = util.create_tenant(self.tenant, str(self.auth_token)) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - - util.create_tenant_group(self.tenant_group, - self.tenant, - str(self.auth_token)) - util.create_user(self.tenant, self.user, - str(self.auth_token)) - - util.add_user_tenant_group(self.tenant, - self.tenant_group, - self.user, self.auth_token) - resp, content = util.get_user_tenant_group_xml(self.tenant, - self.tenant_group, - str(self.token)) - self.assertEqual(401, int(resp['status'])) - - def test_get_users_tenant_group_forbidden(self): - resp, content = util.create_tenant(self.tenant, str(self.auth_token)) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - util.create_tenant_group(self.tenant_group, - self.tenant, - str(self.auth_token)) - util.create_user(self.tenant, self.user, - str(self.auth_token)) - - util.add_user_tenant_group(self.tenant, - self.tenant_group, - self.user, self.auth_token) - resp, content = util.get_user_tenant_group(self.tenant, - self.tenant_group, - str(self.disabled_token)) - - self.assertEqual(403, int(resp['status'])) - - def test_get_users_tenant_group_forbidden_xml(self): - resp, content = util.create_tenant(self.tenant, str(self.auth_token)) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - util.create_tenant_group(self.tenant_group, - self.tenant, - str(self.auth_token)) - util.create_user(self.tenant, self.user, - str(self.auth_token)) - - util.add_user_tenant_group(self.tenant, - self.tenant_group, - self.user, self.auth_token) - resp, content = util.get_user_tenant_group_xml(self.tenant, - self.tenant_group, - str(self.disabled_token)) - - self.assertEqual(403, int(resp['status'])) - - def test_get_users_tenant_group_expired(self): - resp, content = util.create_tenant(self.tenant, str(self.auth_token)) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - util.create_tenant_group(self.tenant_group, - self.tenant, - str(self.auth_token)) - util.create_user(self.tenant, self.user, - str(self.auth_token)) - - util.add_user_tenant_group(self.tenant, - self.tenant_group, - self.user, self.auth_token) - resp, content = util.get_user_tenant_group(self.tenant, - self.tenant_group, - str(self.exp_auth_token)) - self.assertEqual(403, int(resp['status'])) - - def test_get_users_tenant_group_expired_xml(self): - resp, content = util.create_tenant(self.tenant, str(self.auth_token)) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - util.create_tenant_group(self.tenant_group, - self.tenant, - str(self.auth_token)) - util.create_user(self.tenant, self.user, - str(self.auth_token)) - - util.add_user_tenant_group(self.tenant, - self.tenant_group, - self.user, self.auth_token) - resp, content = util.get_user_tenant_group_xml(self.tenant, - self.tenant_group, - str(self.exp_auth_token)) - - self.assertEqual(403, int(resp['status'])) - - -class DeleteUsersTenantGroupTest(TenantGroupTest): - - def test_delete_user_tenant_group(self): - resp, content = util.create_tenant(self.tenant, str(self.auth_token)) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - util.create_tenant_group(self.tenant_group, - self.tenant, - str(self.auth_token)) - util.create_user(self.tenant, self.user, - str(self.auth_token)) - util.add_user_tenant_group(self.tenant, - self.tenant_group, - self.user, - str(self.auth_token)) - resp, content = util.delete_user_tenant_group(self.tenant, - self.tenant_group, - self.user, - str(self.auth_token)) - - self.assertEqual(204, int(resp['status'])) - - def test_delete_user_tenant_group_xml(self): - resp, content = util.create_tenant(self.tenant, str(self.auth_token)) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - util.create_tenant_group(self.tenant_group, - self.tenant, - str(self.auth_token)) - util.create_user(self.tenant, self.user, - str(self.auth_token)) - util.add_user_tenant_group_xml(self.tenant, - self.tenant_group, - self.user, - str(self.auth_token)) - resp, content = util.delete_user_tenant_group_xml(self.tenant, - self.tenant_group, - self.user, - str(self.auth_token)) - - self.assertEqual(204, int(resp['status'])) - - def test_delete_user_tenant_group_notfound(self): - resp, content = util.delete_user_tenant_group(self.tenant, - self.tenant_group, - 'NonExistinguser', - str(self.auth_token)) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(404, int(resp['status'])) - - def test_delete_user_tenant_group_notfound_xml(self): - resp, content = util.delete_user_tenant_group_xml(self.tenant, - self.tenant_group, - 'NonExistinguser', - str(self.auth_token)) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(404, int(resp['status'])) - -if __name__ == '__main__': - unittest.main() diff --git a/test/unit/test_tenants.py b/test/unit/test_tenants.py deleted file mode 100644 index bc639904..00000000 --- a/test/unit/test_tenants.py +++ /dev/null @@ -1,661 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright (c) 2010-2011 OpenStack, LLC. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -import httplib2 -import json -from lxml import etree -import os -import sys -sys.path.append(os.path.abspath(os.path.join(os.path.abspath(__file__), - '..', '..', '..', '..', 'keystone'))) -import unittest - -import test_common as utils - - -class TenantTest(unittest.TestCase): - - def setUp(self): - self.tenant = 'test_tenant' - self.auth_token = utils.get_auth_token() - self.user = utils.get_user() - self.userdisabled = utils.get_userdisabled() - self.exp_auth_token = utils.get_exp_auth_token() - self.disabled_token = utils.get_disabled_token() - utils.create_tenant(self.tenant, str(self.auth_token)) - utils.create_user(self.tenant, self.user, self.auth_token) - utils.add_user_json(self.tenant, self.user, self.auth_token) - self.token = utils.get_token(self.user, 'secrete', self.tenant, - 'token') - - def tearDown(self): - utils.delete_user(self.tenant, self.user, self.auth_token) - utils.delete_tenant(self.tenant, self.auth_token) - - -class CreateTenantTest(TenantTest): - - def test_tenant_create(self): - utils.delete_user(self.tenant, self.user, self.auth_token) - utils.delete_tenant(self.tenant, str(self.auth_token)) - resp, content = utils.create_tenant(self.tenant, str(self.auth_token)) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - - if int(resp['status']) not in (200, 201): - - self.fail('Failed due to %d' % int(resp['status'])) - - def test_tenant_create_xml(self): - utils.delete_user(self.tenant, self.user, self.auth_token) - utils.delete_tenant_xml(self.tenant, - str(self.auth_token)) - resp, content = utils.create_tenant_xml(self.tenant, - str(self.auth_token)) - content = etree.fromstring(content) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - if int(resp['status']) not in (200, 201): - self.fail('Failed due to %d' % int(resp['status'])) - - def test_tenant_create_again(self): - - resp, content = utils.create_tenant(self.tenant, - str(self.auth_token)) - if int(resp['status']) == 200: - self.tenant = content['tenant']['id'] - resp, content = utils.create_tenant(self.tenant, - str(self.auth_token)) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(409, int(resp['status'])) - - def test_tenant_create_again_xml(self): - - resp, content = utils.create_tenant_xml(self.tenant, - str(self.auth_token)) - resp, content = utils.create_tenant_xml(self.tenant, - str(self.auth_token)) - content = etree.fromstring(content) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(409, int(resp['status'])) - - def test_tenant_create_forbidden_token(self): - header = httplib2.Http(".cache") - resp, content = utils.create_tenant(self.tenant, str(self.auth_token)) - if int(resp['status']) == 200: - self.tenant = content['tenant']['id'] - - url = '%stenants' % (utils.URL) - body = {"tenant": {"id": self.tenant, - "description": "A description ...", - "enabled": True}} - resp, content = header.request(url, "POST", body=json.dumps(body), - headers={"Content-Type": "application/json", - "X-Auth-Token": self.token}) - - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(401, int(resp['status'])) - - def test_tenant_create_forbidden_token_xml(self): - header = httplib2.Http(".cache") - resp, content = utils.create_tenant_xml(self.tenant, - str(self.auth_token)) - content = etree.fromstring(content) - if int(resp['status']) == 200: - self.tenant = content.get('id') - - url = '%stenants' % (utils.URL) - body = ' \ - \ - A description... \ - ' % self.tenant - resp, content = header.request(url, "POST", body=body, - headers={"Content-Type": "application/xml", - "X-Auth-Token": self.token, - "ACCEPT": "application/xml"}) - - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(401, int(resp['status'])) - - def test_tenant_create_expired_token(self): - header = httplib2.Http(".cache") - resp, content = utils.create_tenant(self.tenant, - str(self.auth_token)) - if int(resp['status']) == 200: - self.tenant = content['tenant']['id'] - url = '%stenants' % (utils.URL) - body = {"tenant": {"id": self.tenant, - "description": "A description ...", - "enabled": True}} - resp, content = header.request(url, "POST", body=json.dumps(body), - headers={"Content-Type": "application/json", - "X-Auth-Token": self.exp_auth_token}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(403, int(resp['status'])) - - def test_tenant_create_expired_token_xml(self): - header = httplib2.Http(".cache") - resp, content = utils.create_tenant_xml(self.tenant, - str(self.auth_token)) - content = etree.fromstring(content) - if int(resp['status']) == 200: - self.tenant = content.get('id') - - url = '%stenants' % (utils.URL) - body = ' \ - \ - A description... \ - ' % self.tenant - - resp, content = header.request(url, "POST", body=body, - headers={"Content-Type": "application/xml", - "X-Auth-Token": self.exp_auth_token, - "ACCEPT": "application/xml"}) - - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(403, int(resp['status'])) - - def test_tenant_create_missing_token(self): - header = httplib2.Http(".cache") - resp, content = utils.create_tenant(self.tenant, - str(self.auth_token)) - if int(resp['status']) == 200: - self.tenant = content['tenant']['id'] - - url = '%stenants' % (utils.URL) - body = {"tenant": {"id": self.tenant, - "description": "A description ...", - "enabled": True}} - resp, content = header.request(url, "POST", body=json.dumps(body), - headers={"Content-Type": "application/json"}) - - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(401, int(resp['status'])) - - def test_tenant_create_missing_token_xml(self): - header = httplib2.Http(".cache") - resp, content = utils.create_tenant_xml(self.tenant, - str(self.auth_token)) - content = etree.fromstring(content) - if int(resp['status']) == 200: - self.tenant = content.get('id') - url = '%stenants' % (utils.URL) - body = ' \ - \ - A description... \ - ' % self.tenant - resp, content = header.request(url, "POST", body=body, - headers={"Content-Type": "application/xml", - "ACCEPT": "application/xml"}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(401, int(resp['status'])) - - def test_tenant_create_disabled_token(self): - header = httplib2.Http(".cache") - resp, content = utils.create_tenant(self.tenant, - str(self.auth_token)) - if int(resp['status']) == 200: - self.tenant = content['tenant']['id'] - - url = '%stenants' % (utils.URL) - body = '{"tenant": { "id": "%s", \ - "description": "A description ...", "enabled"\ - :true } }' % self.tenant - resp, content = header.request(url, "POST", body=body, - headers={"Content-Type": "application/json", - "X-Auth-Token": self.disabled_token}) - - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(403, int(resp['status'])) - - def test_tenant_create_disabled_token_xml(self): - header = httplib2.Http(".cache") - resp, content = utils.create_tenant_xml(self.tenant, - str(self.auth_token)) - content = etree.fromstring(content) - if int(resp['status']) == 200: - self.tenant = content.get('id') - url = '%stenants' % (utils.URL) - body = ' \ - \ - A description... \ - ' % self.tenant - resp, content = header.request(url, "POST", body=body, - headers={"Content-Type": "application/xml", - "X-Auth-Token": self.disabled_token, - "ACCEPT": "application/xml"}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(403, int(resp['status'])) - - def test_tenant_create_invalid_token(self): - header = httplib2.Http(".cache") - resp, content = utils.create_tenant(self.tenant, - str(self.auth_token)) - if int(resp['status']) == 200: - self.tenant = content['tenant']['id'] - - url = '%stenants' % (utils.URL) - body = '{"tenant": { "id": "%s", \ - "description": "A description ...", "enabled"\ - :true } }' % self.tenant - resp, content = header.request(url, "POST", body=body, - headers={"Content-Type": "application/json", - "X-Auth-Token": 'nonexsitingtoken'}) - - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(404, int(resp['status'])) - - def test_tenant_create_invalid_token_xml(self): - header = httplib2.Http(".cache") - resp, content = utils.create_tenant_xml(self.tenant, - str(self.auth_token)) - content = etree.fromstring(content) - if int(resp['status']) == 200: - self.tenant = content.get('id') - - url = '%stenants' % (utils.URL) - body = ' \ - \ - A description... \ - ' % self.tenant - resp, content = header.request(url, "POST", body=body, - headers={"Content-Type": "application/xml", - "X-Auth-Token": 'nonexsitingtoken', - "ACCEPT": "application/xml"}) - - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(404, int(resp['status'])) - - -class GetTenantsTest(TenantTest): - - def test_get_tenants_using_admin_token(self): - header = httplib2.Http(".cache") - resp, content = utils.create_tenant(self.tenant, str(self.auth_token)) - url = '%stenants' % (utils.URL) - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body='{}', - headers={"Content-Type": "application/json", - "X-Auth-Token": self.auth_token}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(200, int(resp['status'])) - - def test_get_tenants_using_admin_token_xml(self): - header = httplib2.Http(".cache") - resp, content = utils.create_tenant(self.tenant, str(self.auth_token)) - url = '%stenants' % (utils.URL) - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body='', - headers={"Content-Type": "application/xml", - "X-Auth-Token": self.auth_token, - "ACCEPT": "application/xml"}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(200, int(resp['status'])) - - def test_get_tenants_using_user_token(self): - header = httplib2.Http(".cache") - resp, content = utils.create_tenant(self.tenant, str(self.auth_token)) - url = '%stenants' % (utils.URL) - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body='{}', - headers={"Content-Type": "application/json", - "X-Auth-Token": self.token}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(200, int(resp['status'])) - - def test_get_tenants_using_user_token_xml(self): - header = httplib2.Http(".cache") - resp, content = utils.create_tenant(self.tenant, str(self.auth_token)) - url = '%stenants' % (utils.URL) - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body='', - headers={"Content-Type": "application/xml", - "X-Auth-Token": self.token, - "ACCEPT": "application/xml"}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(200, int(resp['status'])) - - def test_get_tenants_exp_token(self): - header = httplib2.Http(".cache") - resp, content = utils.create_tenant(self.tenant, str(self.auth_token)) - url = '%stenants' % (utils.URL) - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body='{}', - headers={"Content-Type": "application/json", - "X-Auth-Token": self.exp_auth_token}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(403, int(resp['status'])) - - def test_get_tenants_exp_token_xml(self): - header = httplib2.Http(".cache") - resp, content = utils.create_tenant(self.tenant, str(self.auth_token)) - url = '%stenants' % (utils.URL) - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body='', - headers={"Content-Type": "application/xml", - "X-Auth-Token": self.exp_auth_token, - "ACCEPT": "application/xml"}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(403, int(resp['status'])) - - -class GetTenantTest(TenantTest): - - def test_get_tenant(self): - header = httplib2.Http(".cache") - resp, content = utils.create_tenant(self.tenant, str(self.auth_token)) - url = '%stenants/%s' % (utils.URL, self.tenant) - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body='{}', - headers={"Content-Type": "application/json", - "X-Auth-Token": self.auth_token}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(200, int(resp['status'])) - - def test_get_tenant_xml(self): - header = httplib2.Http(".cache") - resp, content = utils.create_tenant(self.tenant, str(self.auth_token)) - url = '%stenants/%s' % (utils.URL, self.tenant) - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body='', - headers={"Content-Type": "application/xml", - "X-Auth-Token": self.auth_token, - "ACCEPT": "application/xml"}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(200, int(resp['status'])) - - def test_get_tenant_bad(self): - header = httplib2.Http(".cache") - resp, content = utils.create_tenant(self.tenant, str(self.auth_token)) - url = '%stenants/%s' % (utils.URL, 'tenant_bad') - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body='', - headers={"Content-Type": "application/json", - "X-Auth-Token": self.auth_token}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(404, int(resp['status'])) - - def test_get_tenant_bad_xml(self): - header = httplib2.Http(".cache") - resp, content = utils.create_tenant(self.tenant, str(self.auth_token)) - url = '%stenants/%s' % (utils.URL, 'tenant_bad') - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body='', - headers={"Content-Type": "application/xml", - "X-Auth-Token": self.auth_token, - "ACCEPT": "application/xml"}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(404, int(resp['status'])) - - def test_get_tenant_not_found(self): - header = httplib2.Http(".cache") - resp, content = utils.create_tenant(self.tenant, str(self.auth_token)) - url = '%stenants/NonexistingID' % (utils.URL) - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body='{}', - headers={"Content-Type": "application/json", - "X-Auth-Token": self.auth_token}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(404, int(resp['status'])) - - def test_get_tenant_not_found_xml(self): - header = httplib2.Http(".cache") - resp, content = utils.create_tenant(self.tenant, str(self.auth_token)) - url = '%stenants/NonexistingID' % (utils.URL) - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body='', - headers={"Content-Type": "application/xml", - "X-Auth-Token": self.auth_token, - "ACCEPT": "application/xml"}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(404, int(resp['status'])) - - -class UpdateTenantTest(TenantTest): - - def test_update_tenant(self): - header = httplib2.Http(".cache") - resp, content = utils.create_tenant(self.tenant, str(self.auth_token)) - url = '%stenants/%s' % (utils.URL, self.tenant) - data = '{"tenant": { "description": "A NEW description..." ,\ - "enabled":true }}' - #test for Content-Type = application/json - resp, content = header.request(url, "PUT", body=data, - headers={"Content-Type": "application/json", - "X-Auth-Token": self.auth_token}) - body = json.loads(content) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(200, int(resp['status'])) - self.assertEqual(self.tenant, body['tenant']['id']) - self.assertEqual('A NEW description...', body['tenant']['description']) - - def test_update_tenant_xml(self): - header = httplib2.Http(".cache") - resp, content = utils.create_tenant_xml(self.tenant, - str(self.auth_token)) - url = '%stenants/%s' % (utils.URL, self.tenant) - data = ' \ - \ - A NEW description... \ - ' - - #test for Content-Type = application/json - resp, content = header.request(url, "PUT", body=data, - headers={"Content-Type": "application/xml", - "X-Auth-Token": self.auth_token, - "ACCEPT": "application/xml"}) - body = etree.fromstring(content) - desc = body.find("{http://docs.openstack.org/identity/api/v2.0}description") - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(200, int(resp['status'])) - self.assertEqual(self.tenant, body.get('id')) - self.assertEqual('A NEW description...', desc.text) - - def test_update_tenant_bad(self): - header = httplib2.Http(".cache") - resp, content = utils.create_tenant(self.tenant, str(self.auth_token)) - url = '%stenants/%s' % (utils.URL, self.tenant) - data = '{"tenant": { "description_bad": "A NEW description...",\ - "enabled":true }}' - #test for Content-Type = application/json - - resp, content = header.request(url, "PUT", body=data, - headers={"Content-Type": "application/json", - "X-Auth-Token": self.auth_token}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(400, int(resp['status'])) - - def test_update_tenant_bad_xml(self): - header = httplib2.Http(".cache") - resp, content = utils.create_tenant(self.tenant, str(self.auth_token)) - url = '%stenants/%s' % (utils.URL, self.tenant) - data = ' \ - \ - A NEW description... \ - ' - #test for Content-Type = application/json - resp, content = header.request(url, "PUT", body=data, - headers={"Content-Type": "application/xml", - "X-Auth-Token": self.auth_token, - "ACCEPT": "application/xml"}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(400, int(resp['status'])) - - def test_update_tenant_not_found(self): - header = httplib2.Http(".cache") - resp, content = utils.create_tenant(self.tenant, str(self.auth_token)) - url = '%stenants/NonexistingID' % (utils.URL) - data = '{"tenant": { "description": "A NEW description...",\ - "enabled":true }}' - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body=data, - headers={"Content-Type": "application/json", - "X-Auth-Token": self.auth_token}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(404, int(resp['status'])) - - def test_update_tenant_not_found_xml(self): - header = httplib2.Http(".cache") - resp, content = utils.create_tenant(self.tenant, str(self.auth_token)) - url = '%stenants/NonexistingID' % (utils.URL) - data = ' \ - \ - A NEW description... \ - ' - #test for Content-Type = application/json - resp, content = header.request(url, "GET", body=data, - headers={"Content-Type": "application/xml", - "X-Auth-Token": self.auth_token, - "ACCEPT": "application/xml"}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(404, int(resp['status'])) - - -class DeleteTenantTest(TenantTest): - - def test_delete_tenant_not_found(self): - #resp,content=utils.create_tenant("test_tenant_delete", - # str(self.auth_token)) - resp = utils.delete_tenant("test_tenant_delete111", - str(self.auth_token)) - self.assertEqual(404, int(resp['status'])) - - def test_delete_tenant_not_found_xml(self): - #resp,content=utils.create_tenant("test_tenant_delete", - # str(self.auth_token)) - resp = utils.delete_tenant_xml("test_tenant_delete111", - str(self.auth_token)) - self.assertEqual(404, int(resp['status'])) - - def test_delete_tenant(self): - resp, content = utils.create_tenant("test_tenant_delete", - str(self.auth_token)) - resp = utils.delete_tenant("test_tenant_delete", - str(self.auth_token)) - self.assertEqual(204, int(resp['status'])) - - def test_delete_tenant_xml(self): - resp, content = utils.create_tenant_xml("test_tenant_delete", - str(self.auth_token)) - resp = utils.delete_tenant_xml("test_tenant_delete", - str(self.auth_token)) - self.assertEqual(204, int(resp['status'])) - -if __name__ == '__main__': - unittest.main() diff --git a/test/unit/test_token.py b/test/unit/test_token.py deleted file mode 100644 index 0754f777..00000000 --- a/test/unit/test_token.py +++ /dev/null @@ -1,173 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright (c) 2010-2011 OpenStack, LLC. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -import httplib2 -import os -import sys -sys.path.append(os.path.abspath(os.path.join(os.path.abspath(__file__), - '..', '..', '..', '..', 'keystone'))) -import unittest -import test_common as utils -import json -import keystone.logic.types.fault as fault -from lxml import etree - -class ValidateToken(unittest.TestCase): - - def setUp(self): - self.tenant = utils.get_tenant() - self.user = 'joeuser' - self.token = utils.get_token('joeuser', 'secrete', self.tenant, - 'token') - #self.user = utils.get_user() - #self.userdisabled = utils.get_userdisabled() - self.auth_token = utils.get_auth_token() - self.exp_auth_token = utils.get_exp_auth_token() - #self.disabled_token = utils.get_disabled_token() - resp, content = utils.create_role_ref(self.user, 'Admin', self.tenant, str(self.auth_token)) - obj = json.loads(content) - if not "roleRef" in obj: - raise fault.BadRequestFault("Expecting RoleRef") - roleRef = obj["roleRef"] - if not "id" in roleRef: - self.role_ref_id = None - else: - self.role_ref_id = roleRef["id"] - - - def tearDown(self): - resp, content = utils.delete_role_ref(self.user, self.role_ref_id, self.auth_token) - utils.delete_token(self.token, self.auth_token) - - def test_validate_token_true(self): - header = httplib2.Http(".cache") - - url = '%stokens/%s?belongsTo=%s' % (utils.URL, self.token, self.tenant) - resp, content = header.request(url, "GET", body='', - headers={"Content-Type": "application/json", - "X-Auth-Token": self.auth_token}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(200, int(resp['status'])) - self.assertEqual('application/json', utils.content_type(resp)) - #verify content - obj = json.loads(content) - if not "auth" in obj: - raise self.fail("Expecting Auth") - role_refs = obj["auth"]["user"]["roleRefs"] - role_ref = role_refs[0] - role_ref_id = role_ref["id"] - self.assertEqual(self.role_ref_id, role_ref_id) - - def test_validate_token_true_xml(self): - header = httplib2.Http(".cache") - url = '%stokens/%s?belongsTo=%s' % (utils.URL, self.token, self.tenant) - resp, content = header.request(url, "GET", body='', - headers={"Content-Type": "application/xml", - "X-Auth-Token": self.auth_token, - "ACCEPT": "application/xml"}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(200, int(resp['status'])) - self.assertEqual('application/xml', utils.content_type(resp)) - #verify content - dom = etree.Element("root") - dom.append(etree.fromstring(content)) - auth = dom.find("{http://docs.openstack.org/identity/api/v2.0}" \ - "auth") - if auth == None: - self.fail("Expecting Auth") - - user = auth.find("{http://docs.openstack.org/identity/api/v2.0}" \ - "user") - if user == None: - self.fail("Expecting User") - roleRefs = user.find("{http://docs.openstack.org/identity/api/v2.0}" \ - "roleRefs") - if roleRefs == None: - self.fail("Expecting Role Refs") - roleRef = roleRefs.find("{http://docs.openstack.org/identity/api/v2.0}" \ - "roleRef") - if roleRef == None: - self.fail("Expecting Role Refs") - self.assertEqual(str(self.role_ref_id), roleRef.get("id")) - - def test_validate_token_expired(self): - header = httplib2.Http(".cache") - url = '%stokens/%s?belongsTo=%s' % (utils.URL, self.exp_auth_token, - self.tenant) - resp, content = header.request(url, "GET", body='', - headers={"Content-Type": "application/json", - "X-Auth-Token": self.exp_auth_token}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(403, int(resp['status'])) - self.assertEqual('application/json', utils.content_type(resp)) - - def test_validate_token_expired_xml(self): - header = httplib2.Http(".cache") - - url = '%stokens/%s?belongsTo=%s' % (utils.URL, self.exp_auth_token, - self.tenant) - resp, content = header.request(url, "GET", body='', - headers={"Content-Type": "application/xml", - "X-Auth-Token": self.exp_auth_token, - "ACCEPT": "application/xml"}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(403, int(resp['status'])) - self.assertEqual('application/xml', utils.content_type(resp)) - - def test_validate_token_invalid(self): - header = httplib2.Http(".cache") - url = '%stokens/%s?belongsTo=%s' % (utils.URL, 'NonExistingToken', - self.tenant) - resp, content = header.request(url, "GET", body='', - headers={"Content-Type": "application/json", - "X-Auth-Token": self.auth_token}) - - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(401, int(resp['status'])) - self.assertEqual('application/json', utils.content_type(resp)) - - def test_validate_token_invalid_xml(self): - header = httplib2.Http(".cache") - url = '%stokens/%s?belongsTo=%s' % (utils.URL, 'NonExistingToken', - self.tenant) - resp, content = header.request(url, "GET", body='', - headers={"Content-Type": "application/json", - "X-Auth-Token": self.auth_token}) - if int(resp['status']) == 500: - self.fail('Identity Fault') - elif int(resp['status']) == 503: - self.fail('Service Not Available') - self.assertEqual(401, int(resp['status'])) - self.assertEqual('application/json', utils.content_type(resp)) - -if __name__ == '__main__': - unittest.main() diff --git a/test/unit/test_users.py b/test/unit/test_users.py deleted file mode 100644 index 083da21f..00000000 --- a/test/unit/test_users.py +++ /dev/null @@ -1,1584 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright (c) 2010-2011 OpenStack, LLC. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -import httplib2 -import json -from lxml import etree -import os -import sys -sys.path.append(os.path.abspath(os.path.join(os.path.abspath(__file__), - '..', '..', '..', '..', 'keystone'))) -import unittest - -import test_common as utils -from test_common import URL - - -class UserTest(unittest.TestCase): - - def setUp(self): - self.tenant = utils.get_tenant() - self.password = utils.get_password() - self.email = utils.get_email() - self.user = utils.get_user() - self.userdisabled = utils.get_userdisabled() - self.auth_token = utils.get_auth_token() - self.exp_auth_token = utils.get_exp_auth_token() - self.disabled_token = utils.get_disabled_token() - self.missing_token = utils.get_none_token() - self.invalid_token = utils.get_non_existing_token() - utils.create_tenant(self.tenant, str(self.auth_token)) - utils.add_user_json(self.tenant, self.user, self.auth_token) - self.token = utils.get_token(self.user, 'secrete', self.tenant, - 'token') - - def tearDown(self): - utils.delete_user(self.tenant, self.user, str(self.auth_token)) - - -class CreateUserTest(UserTest): - - def test_a_user_create_json(self): - - resp = utils.delete_user(self.tenant, self.user, str(self.auth_token)) - - resp, content = utils.create_user(self.tenant, 'test_user1', - str(self.auth_token)) - self.user = 'test_user1' - resp_val = int(resp['status']) - utils.handle_user_resp(self, content, resp_val, - utils.content_type(resp)) - self.assertEqual(201, resp_val) - - def test_a_user_create_xml(self): - utils.delete_user_xml(self.tenant, self.user, str(self.auth_token)) - resp, content = utils.create_user_xml(self.tenant, 'test_user1', - str(self.auth_token)) - self.user = 'test_user1' - resp_val = int(resp['status']) - utils.handle_user_resp(self, content, resp_val, - utils.content_type(resp)) - self.assertEqual(201, resp_val) - self.assertEqual('application/xml', utils.content_type(resp)) - - def test_a_user_create_json_disabled_tenant(self): - resp, content = utils.create_user('0000', self.user, - str(self.auth_token)) - resp_val = int(resp['status']) - utils.handle_user_resp(self, content, resp_val, - utils.content_type(resp)) - self.assertEqual(403, resp_val) - - def test_a_user_create_json_disabled_tenant_xml(self): - resp, content = utils.create_user_xml('0000', self.user, - str(self.auth_token)) - resp_val = int(resp['status']) - utils.handle_user_resp(self, content, resp_val, - utils.content_type(resp)) - self.assertEqual(403, resp_val) - self.assertEqual('application/xml', utils.content_type(resp)) - - def test_a_user_create_again_json(self): - resp, content = utils.create_user(self.tenant, self.user, - str(self.auth_token)) - resp_val = int(resp['status']) - utils.handle_user_resp(self, content, resp_val, - utils.content_type(resp)) - resp, content = utils.create_user(self.tenant, self.user, - str(self.auth_token)) - self.assertEqual(409, int(resp['status'])) - - def test_a_user_create_again_xml(self): - utils.create_user_xml(self.tenant, self.user, - str(self.auth_token)) - resp, content = utils.create_user_xml(self.tenant, self.user, - str(self.auth_token)) - content = etree.fromstring(content) - resp_val = int(resp['status']) - utils.handle_user_resp(self, content, resp_val, - utils.content_type(resp)) - self.assertEqual(409, int(resp['status'])) - self.assertEqual('application/xml', utils.content_type(resp)) - - def test_a_user_create_email_conflict(self): - utils.create_user(self.tenant, self.user, str(self.auth_token), - self.email) - resp, content = utils.create_user(self.tenant, self.user, - str(self.auth_token), - self.email) - self.assertEqual(409, int(resp['status'])) - - def test_a_user_create_email_conflict_xml(self): - utils.create_user_xml(self.tenant, - self.user, - str(self.auth_token), - self.email) - resp, content = utils.create_user_xml(self.tenant, self.user, - str(self.auth_token), - self.email) - content = etree.fromstring(content) - resp_val = int(resp['status']) - utils.handle_user_resp(self, content, resp_val, - utils.content_type(resp)) - self.assertEqual(409, int(resp['status'])) - self.assertEqual('application/xml', utils.content_type(resp)) - - def test_a_user_create_expired_token(self): - resp, content = utils.create_user(self.tenant, self.user, - str(self.exp_auth_token)) - resp_val = int(resp['status']) - utils.handle_user_resp(self, content, resp_val, - utils.content_type(resp)) - self.assertEqual(403, int(resp['status'])) - - def test_a_user_create_expired_token_xml(self): - resp, content = utils.create_user_xml(self.tenant, self.user, - str(self.exp_auth_token)) - resp_val = int(resp['status']) - utils.handle_user_resp(self, content, resp_val, - utils.content_type(resp)) - self.assertEqual(403, int(resp['status'])) - self.assertEqual('application/xml', utils.content_type(resp)) - - def test_a_user_create_disabled_token(self): - resp, content = utils.create_user(self.tenant, self.user, - str(self.disabled_token)) - resp_val = int(resp['status']) - utils.handle_user_resp(self, content, resp_val, - utils.content_type(resp)) - self.assertEqual(403, int(resp['status'])) - - def test_a_user_create_disabled_token_xml(self): - resp, content = utils.create_user_xml(self.tenant, self.user, - str(self.disabled_token)) - resp_val = int(resp['status']) - utils.handle_user_resp(self, content, resp_val, - utils.content_type(resp)) - self.assertEqual(403, int(resp['status'])) - self.assertEqual('application/xml', utils.content_type(resp)) - - def test_a_user_create_missing_token(self): - resp, content = utils.create_user(self.tenant, self.user, - str(self.missing_token)) - resp_val = int(resp['status']) - utils.handle_user_resp(self, content, resp_val, - utils.content_type(resp)) - self.assertEqual(401, int(resp['status'])) - - def test_a_user_create_missing_token_xml(self): - resp, content = utils.create_user_xml(self.tenant, self.user, - str(self.missing_token)) - resp_val = int(resp['status']) - utils.handle_user_resp(self, content, resp_val, - utils.content_type(resp)) - self.assertEqual(401, int(resp['status'])) - self.assertEqual('application/xml', utils.content_type(resp)) - - def test_a_user_create_invalid_token(self): - resp, content = utils.create_user(self.tenant, self.user, - str(self.invalid_token)) - resp_val = int(resp['status']) - utils.handle_user_resp(self, content, resp_val, - utils.content_type(resp)) - self.assertEqual(404, int(resp['status'])) - - def test_a_user_create_invalid_token_xml(self): - resp, content = utils.create_user_xml(self.tenant, self.user, - str(self.invalid_token)) - resp_val = int(resp['status']) - utils.handle_user_resp(self, content, resp_val, - utils.content_type(resp)) - self.assertEqual(404, int(resp['status'])) - self.assertEqual('application/xml', utils.content_type(resp)) - - -class GetUserTest(UserTest): - - def test_a_user_get(self): - utils.create_user(self.tenant, self.user, str(self.auth_token)) - resp, content = utils.user_get_json(self.tenant, self.user, - str(self.auth_token)) - resp_val = int(resp['status']) - utils.handle_user_resp(self, content, resp_val, - utils.content_type(resp)) - self.assertEqual(200, resp_val) - - def test_a_user_get_xml(self): - utils.create_user(self.tenant, self.user, str(self.auth_token)) - resp, content = utils.user_get_xml(self.tenant, self.user, - str(self.auth_token)) - resp_val = int(resp['status']) - utils.handle_user_resp(self, content, resp_val, - utils.content_type(resp)) - self.assertEqual(200, resp_val) - self.assertEqual('application/xml', utils.content_type(resp)) - - def test_a_user_get_expired_token(self): - utils.create_user(self.tenant, self.user, str(self.auth_token)) - resp, content = utils.user_get_json(self.tenant, self.user, - str(self.exp_auth_token)) - resp_val = int(resp['status']) - utils.handle_user_resp(self, content, resp_val, - utils.content_type(resp)) - self.assertEqual(403, resp_val) - - def test_a_user_get_expired_token_xml(self): - utils.create_user(self.tenant, self.user, str(self.auth_token)) - resp, content = utils.user_get_xml(self.tenant, self.user, - str(self.exp_auth_token)) - resp_val = int(resp['status']) - utils.handle_user_resp(self, content, resp_val, - utils.content_type(resp)) - self.assertEqual(403, resp_val) - self.assertEqual('application/xml', utils.content_type(resp)) - - def test_a_user_get_disabled_token(self): - utils.create_user(self.tenant, self.user, str(self.auth_token)) - resp, content = utils.user_get_json(self.tenant, - self.user, - str(self.disabled_token)) - resp_val = int(resp['status']) - utils.handle_user_resp(self, content, resp_val, - utils.content_type(resp)) - self.assertEqual(403, resp_val) - - def test_a_user_get_disabled_token_xml(self): - utils.create_user(self.tenant, self.user, str(self.auth_token)) - resp, content = utils.user_get_xml(self.tenant, - self.user, - str(self.disabled_token)) - resp_val = int(resp['status']) - utils.handle_user_resp(self, content, resp_val, - utils.content_type(resp)) - self.assertEqual(403, resp_val) - self.assertEqual('application/xml', utils.content_type(resp)) - - def test_a_user_get_missing_token(self): - utils.create_user(self.tenant, self.user, str(self.auth_token)) - resp, content = utils.user_get_json(self.tenant, - self.user, - str(self.missing_token)) - resp_val = int(resp['status']) - utils.handle_user_resp(self, content, resp_val, - utils.content_type(resp)) - self.assertEqual(401, resp_val) - - def test_a_user_get_missing_token_xml(self): - utils.create_user(self.tenant, self.user, str(self.auth_token)) - resp, content = utils.user_get_xml(self.tenant, self.user, - str(self.missing_token)) - resp_val = int(resp['status']) - utils.handle_user_resp(self, content, resp_val, - utils.content_type(resp)) - self.assertEqual(401, resp_val) - self.assertEqual('application/xml', utils.content_type(resp)) - - def test_a_user_get_invalid_token(self): - utils.create_user(self.tenant, self.user, str(self.auth_token)) - resp, content = utils.user_get_json(self.tenant, self.user, - str(self.invalid_token)) - resp_val = int(resp['status']) - utils.handle_user_resp(self, content, resp_val, - utils.content_type(resp)) - self.assertEqual(404, resp_val) - - def test_a_user_get_invalid_token_xml(self): - utils.create_user(self.tenant, self.user, str(self.auth_token)) - resp, content = utils.user_get_xml(self.tenant, self.user, - str(self.invalid_token)) - resp_val = int(resp['status']) - utils.handle_user_resp(self, content, resp_val, - utils.content_type(resp)) - self.assertEqual(404, resp_val) - self.assertEqual('application/xml', utils.content_type(resp)) - - def test_a_user_get_disabled_user(self): - utils.create_user(self.tenant, self.user, str(self.auth_token)) - resp, content = utils.user_get_json(self.tenant, - self.userdisabled, - str(self.auth_token)) - resp_val = int(resp['status']) - utils.handle_user_resp(self, content, resp_val, - utils.content_type(resp)) - self.assertEqual(403, resp_val) - - def test_a_user_get_disabled_user_xml(self): - utils.create_user(self.tenant, self.user, str(self.auth_token)) - resp, content = utils.user_get_xml(self.tenant, self.userdisabled, - str(self.auth_token)) - resp_val = int(resp['status']) - utils.handle_user_resp(self, content, resp_val, - utils.content_type(resp)) - self.assertEqual(403, resp_val) - self.assertEqual('application/xml', utils.content_type(resp)) - - def test_a_user_get_disabled_tenant(self): - utils.create_user(self.tenant, self.user, str(self.auth_token)) - resp, content = utils.user_get_json('0000', self.user, - str(self.auth_token)) - resp_val = int(resp['status']) - utils.handle_user_resp(self, content, resp_val, - utils.content_type(resp)) - self.assertEqual(403, resp_val) - - def test_a_user_get_disabled_tenant_xml(self): - utils.create_user(self.tenant, self.user, str(self.auth_token)) - resp, content = utils.user_get_xml('0000', self.user, - str(self.auth_token)) - resp_val = int(resp['status']) - utils.handle_user_resp(self, content, resp_val, - utils.content_type(resp)) - self.assertEqual(403, resp_val) - self.assertEqual('application/xml', - utils.content_type(resp)) - - -class DeleteUserTest(UserTest): - - def test_a_user_delete(self): - utils.create_user(self.tenant, self.user, - str(self.auth_token)) - resp = utils.delete_user(self.tenant, self.user, - str(self.auth_token)) - resp_val = int(resp['status']) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(204, resp_val) - - def test_a_user_delete_xml(self): - utils.create_user(self.tenant, self.user, - str(self.auth_token)) - resp = utils.delete_user_xml(self.tenant, self.user, - str(self.auth_token)) - resp_val = int(resp['status']) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(204, resp_val) - - def test_a_user_delete_expired_token(self): - utils.create_user(self.tenant, self.user, - str(self.auth_token)) - resp = utils.delete_user(self.tenant, self.user, - str(self.exp_auth_token)) - resp_val = int(resp['status']) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(403, resp_val) - - def test_a_user_delete_expired_token_xml(self): - utils.create_user(self.tenant, self.user, - str(self.auth_token)) - resp = utils.delete_user_xml(self.tenant, self.user, - str(self.exp_auth_token)) - resp_val = int(resp['status']) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(403, resp_val) - self.assertEqual('application/xml', utils.content_type(resp)) - - def test_a_user_delete_missing_token(self): - utils.create_user(self.tenant, self.user, - str(self.auth_token)) - resp = utils.delete_user(self.tenant, self.user, - str(self.missing_token)) - resp_val = int(resp['status']) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(401, resp_val) - - def test_a_user_delete_missing_token_xml(self): - utils.create_user(self.tenant, self.user, - str(self.auth_token)) - resp = utils.delete_user_xml(self.tenant, self.user, - str(self.missing_token)) - resp_val = int(resp['status']) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(401, resp_val) - self.assertEqual('application/xml', utils.content_type(resp)) - - def test_a_user_delete_invalid_token(self): - utils.create_user(self.tenant, self.user, - str(self.auth_token)) - resp = utils.delete_user(self.tenant, self.user, - str(self.invalid_token)) - resp_val = int(resp['status']) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(404, resp_val) - - def test_a_user_delete_invalid_token_xml(self): - utils.create_user(self.tenant, self.user, - str(self.auth_token)) - resp = utils.delete_user_xml(self.tenant, self.user, - str(self.invalid_token)) - resp_val = int(resp['status']) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(404, resp_val) - self.assertEqual('application/xml', utils.content_type(resp)) - - def test_a_user_delete_disabled_tenant(self): - utils.create_user(self.tenant, self.user, - str(self.auth_token)) - resp = utils.delete_user("0000", self.user, - str(self.auth_token)) - resp_val = int(resp['status']) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(403, resp_val) - - def test_a_user_delete_disabled_tenant_xml(self): - utils.create_user(self.tenant, self.user, - str(self.auth_token)) - resp = utils.delete_user_xml("0000", self.user, - str(self.auth_token)) - resp_val = int(resp['status']) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(403, resp_val) - self.assertEqual('application/xml', utils.content_type(resp)) - - -class GetUsersTest(UserTest): - - def test_users_get(self): - resp, content = utils.users_get_json(self.tenant, self.auth_token) - resp_val = int(resp['status']) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(200, resp_val) - - def test_users_get_xml(self): - resp, content = utils.users_get_xml(self.tenant, self.auth_token) - resp_val = int(resp['status']) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(200, resp_val) - self.assertEqual('application/xml', utils.content_type(resp)) - - def test_users_get_expired_token(self): - resp, content = utils.users_get_json(self.tenant, self.exp_auth_token) - resp_val = int(resp['status']) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(403, resp_val) - - def test_users_get_expired_token_xml(self): - resp, content = utils.users_get_xml(self.tenant, self.exp_auth_token) - resp_val = int(resp['status']) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(403, resp_val) - self.assertEqual('application/xml', utils.content_type(resp)) - - def test_users_get_disabled_token(self): - resp, content = utils.users_get_json(self.tenant, self.disabled_token) - resp_val = int(resp['status']) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(403, resp_val) - - def test_users_get_disabled_token_xml(self): - resp, content = utils.users_get_xml(self.tenant, self.disabled_token) - resp_val = int(resp['status']) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(403, resp_val) - self.assertEqual('application/xml', utils.content_type(resp)) - - def test_users_get_missing_token(self): - resp, content = utils.users_get_json(self.tenant, self.missing_token) - resp_val = int(resp['status']) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(401, resp_val) - - def test_users_get_missing_token_xml(self): - resp, content = utils.users_get_xml(self.tenant, self.missing_token) - resp_val = int(resp['status']) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(401, resp_val) - self.assertEqual('application/xml', utils.content_type(resp)) - - def test_users_get_invalid_token(self): - resp, content = utils.users_get_json(self.tenant, self.invalid_token) - resp_val = int(resp['status']) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(404, resp_val) - - def test_users_get_invalid_token_xml(self): - resp, content = utils.users_get_xml(self.tenant, self.invalid_token) - resp_val = int(resp['status']) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(404, resp_val) - self.assertEqual('application/xml', utils.content_type(resp)) - - def test_users_get_disabled_tenant(self): - resp, content = utils.users_get_json('0000', self.auth_token) - resp_val = int(resp['status']) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(403, resp_val) - - def test_users_get_disabled_tenant_xml(self): - resp, content = utils.users_get_xml('0000', self.auth_token) - resp_val = int(resp['status']) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(403, resp_val) - self.assertEqual('application/xml', utils.content_type(resp)) - - -class GetUsersGroupTest(UserTest): - - def test_users_group_get(self): - resp, content = utils.users_group_get_json(self.tenant, - self.user, - self.auth_token) - resp_val = int(resp['status']) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(200, resp_val) - - def test_users_group_get_xml(self): - resp, content = utils.users_group_get_xml(self.tenant, - self.user, - self.auth_token) - resp_val = int(resp['status']) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(200, resp_val) - self.assertEqual('application/xml', utils.content_type(resp)) - - def test_users_group_get_expired_token(self): - resp, content = utils.users_group_get_json(self.tenant, - self.user, - self.exp_auth_token) - resp_val = int(resp['status']) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(403, resp_val) - - def test_users_group_get_expired_token_xml(self): - resp, content = utils.users_group_get_xml(self.tenant, - self.user, - self.exp_auth_token) - resp_val = int(resp['status']) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(403, resp_val) - self.assertEqual('application/xml', utils.content_type(resp)) - - def test_users_group_get_disabled_token(self): - resp, content = utils.users_group_get_json(self.tenant, - self.user, - self.disabled_token) - resp_val = int(resp['status']) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(403, resp_val) - - def test_users_group_get_disabled_token_xml(self): - resp, content = utils.users_group_get_xml(self.tenant, - self.user, - self.disabled_token) - resp_val = int(resp['status']) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(403, resp_val) - self.assertEqual('application/xml', utils.content_type(resp)) - - def test_users_group_get_missing_token(self): - resp, content = utils.users_group_get_json(self.tenant, - self.user, - self.missing_token) - resp_val = int(resp['status']) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(401, resp_val) - - def test_users_group_get_missing_token_xml(self): - resp, content = utils.users_group_get_xml(self.tenant, - self.user, - self.missing_token) - resp_val = int(resp['status']) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(401, resp_val) - self.assertEqual('application/xml', utils.content_type(resp)) - - def test_users_group_get_invalid_token(self): - resp, content = utils.users_group_get_json(self.tenant, - self.user, - self.invalid_token) - resp_val = int(resp['status']) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(404, resp_val) - - def test_users_group_get_invalid_token_xml(self): - resp, content = utils.users_group_get_xml(self.tenant, - self.user, - self.invalid_token) - resp_val = int(resp['status']) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(404, resp_val) - self.assertEqual('application/xml', utils.content_type(resp)) - - def test_users_group_get_disabled_tenant(self): - resp, content = utils.users_group_get_json('0000', - self.user, - self.auth_token) - resp_val = int(resp['status']) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(403, resp_val) - - def test_users_group_get_disabled_tenant_xml(self): - resp, content = utils.users_group_get_xml('0000', - self.user, - self.auth_token) - resp_val = int(resp['status']) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(403, resp_val) - self.assertEqual('application/xml', utils.content_type(resp)) - - -class UpdateUserTest(UserTest): - - def test_user_update(self): - utils.create_user(self.tenant, self.user, str(self.auth_token)) - resp, content = utils.user_update_json(self.tenant, self.user, - self.auth_token) - resp_val = int(resp['status']) - content = json.loads(content) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - utils.delete_user(self.tenant, self.user, str(self.auth_token)) - self.assertEqual(200, resp_val) - self.assertEqual('updatedjoeuser@rackspace.com', - content['user']['email']) - - def test_user_update_xml(self): - utils.create_user(self.tenant, self.user, str(self.auth_token)) - resp, content = utils.user_update_xml(self.tenant, self.user, - self.auth_token) - resp_val = int(resp['status']) - content = etree.fromstring(content) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - utils.delete_user(self.tenant, self.user, str(self.auth_token)) - self.assertEqual(200, resp_val) - self.assertEqual('updatedjoeuser@rackspace.com', - content.get("email")) - self.assertEqual('application/xml', utils.content_type(resp)) - - def test_user_update_user_disabled(self): - utils.create_user(self.tenant, self.user, str(self.auth_token)) - resp, content = utils.user_update_json(self.tenant, - self.userdisabled, - self.auth_token) - resp_val = int(resp['status']) - content = json.loads(content) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(403, resp_val) - - def test_user_update_user_disabled_xml(self): - utils.create_user(self.tenant, self.user, str(self.auth_token)) - resp, content = utils.user_update_xml(self.tenant, - self.userdisabled, - self.auth_token) - resp_val = int(resp['status']) - content = etree.fromstring(content) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(403, resp_val) - self.assertEqual('application/xml', utils.content_type(resp)) - - def test_user_update_email_conflict(self): - utils.create_user(self.tenant, self.user, str(self.auth_token)) - resp, content = utils.user_update_json(self.tenant, - "joeuser", - self.auth_token, - "test_user@rackspace.com") - resp_val = int(resp['status']) - content = json.loads(content) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(409, resp_val) - - def test_user_update_email_conflict_xml(self): - utils.create_user(self.tenant, self.user, str(self.auth_token)) - resp, content = utils.user_update_xml(self.tenant, - "joeuser", - self.auth_token, - "test_user@rackspace.com") - resp_val = int(resp['status']) - content = etree.fromstring(content) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(409, resp_val) - self.assertEqual('application/xml', utils.content_type(resp)) - - def test_user_update_bad_request_json(self): - h = httplib2.Http(".cache") - resp, content = utils.create_user(self.tenant, self.user, - str(self.auth_token)) - url = '%stenants/%s/users/%s' % (URL, self.tenant, self.user) - data = '{"user_bad": { "bad": "updatedjoeuser@rackspace.com"}}' - resp, content = h.request(url, "PUT", body=data, - headers={"Content-Type": "application/json", - "X-Auth-Token": self.auth_token}) - resp_val = int(resp['status']) - content = json.loads(content) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - utils.delete_user(self.tenant, self.user, str(self.auth_token)) - self.assertEqual(400, resp_val) - - def test_user_update_bad_request_xml(self): - h = httplib2.Http(".cache") - resp, content = utils.create_user_xml(self.tenant, self.user, - str(self.auth_token)) - url = '%stenants/%s/users/%s' % (URL, self.tenant, self.user) - data = ' \ - user xmlns="http://docs.openstack.org/identity/api/v2.0" \ - email="updatedjoeuser@rackspace.com" />' - resp, content = h.request(url, "PUT", body=data, - headers={"Content-Type": "application/xml", - "X-Auth-Token": self.auth_token, - "ACCEPT": "application/xml"}) - resp_val = int(resp['status']) - content = etree.fromstring(content) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - utils.delete_user(self.tenant, self.user, str(self.auth_token)) - self.assertEqual(400, resp_val) - self.assertEqual('application/xml', utils.content_type(resp)) - - def test_user_update_expired_token(self): - utils.create_user(self.tenant, self.user, str(self.auth_token)) - resp, content = utils.user_update_json(self.tenant, - self.user, - self.exp_auth_token) - resp_val = int(resp['status']) - content = json.loads(content) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(403, resp_val) - - def test_user_update_expired_token_xml(self): - utils.create_user(self.tenant, self.user, str(self.auth_token)) - resp, content = utils.user_update_xml(self.tenant, - self.user, - self.exp_auth_token) - resp_val = int(resp['status']) - content = etree.fromstring(content) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(403, resp_val) - self.assertEqual('application/xml', utils.content_type(resp)) - - def test_user_update_disabled_token(self): - utils.create_user(self.tenant, self.user, str(self.auth_token)) - resp, content = utils.user_update_json(self.tenant, - self.user, - self.disabled_token) - resp_val = int(resp['status']) - content = json.loads(content) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(403, resp_val) - - def test_user_update_disabled_token_xml(self): - utils.create_user(self.tenant, self.user, str(self.auth_token)) - resp, content = utils.user_update_xml(self.tenant, - self.user, - self.disabled_token) - resp_val = int(resp['status']) - content = etree.fromstring(content) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(403, resp_val) - self.assertEqual('application/xml', utils.content_type(resp)) - - def test_user_update_invalid_token(self): - utils.create_user(self.tenant, self.user, str(self.auth_token)) - resp, content = utils.user_update_json(self.tenant, - self.user, - self.invalid_token) - resp_val = int(resp['status']) - content = json.loads(content) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(404, resp_val) - - def test_user_update_invalid_token_xml(self): - utils.create_user(self.tenant, self.user, str(self.auth_token)) - resp, content = utils.user_update_xml(self.tenant, - self.user, - self.invalid_token) - resp_val = int(resp['status']) - content = etree.fromstring(content) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(404, resp_val) - self.assertEqual('application/xml', utils.content_type(resp)) - - def test_user_update_missing_token(self): - utils.create_user(self.tenant, self.user, str(self.auth_token)) - resp, content = utils.user_update_json(self.tenant, - self.user, - self.missing_token) - resp_val = int(resp['status']) - content = json.loads(content) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(401, resp_val) - - def test_user_update_missing_token_xml(self): - utils.create_user(self.tenant, self.user, str(self.auth_token)) - resp, content = utils.user_update_xml(self.tenant, - self.user, - self.missing_token) - resp_val = int(resp['status']) - content = etree.fromstring(content) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(401, resp_val) - self.assertEqual('application/xml', utils.content_type(resp)) - - -class SetPasswordTest(UserTest): - - def test_user_password(self): - utils.create_user(self.tenant, self.user, str(self.auth_token)) - resp, content = utils.user_password_json(self.tenant, - self.user, - str(self.auth_token)) - resp_val = int(resp['status']) - content = json.loads(content) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - utils.delete_user(self.tenant, self.user, str(self.auth_token)) - self.assertEqual(200, resp_val) - self.assertEqual('p@ssword', content['user']['password']) - - def test_user_password_xml(self): - utils.create_user(self.tenant, self.user, str(self.auth_token)) - resp, content = utils.user_password_xml(self.tenant, - self.user, - str(self.auth_token)) - resp_val = int(resp['status']) - content = etree.fromstring(content) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - utils.delete_user(self.tenant, self.user, str(self.auth_token)) - self.assertEqual(200, resp_val) - self.assertEqual('p@ssword', content.get("password")) - self.assertEqual('application/xml', utils.content_type(resp)) - - def test_user_password_user_disabled(self): - utils.create_user(self.tenant, self.user, str(self.auth_token)) - resp, content = utils.user_password_json(self.tenant, - self.userdisabled, - str(self.auth_token)) - resp_val = int(resp['status']) - content = json.loads(content) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(403, resp_val) - - def test_user_password_user_disabled_xml(self): - utils.create_user(self.tenant, self.user, str(self.auth_token)) - resp, content = utils.user_password_xml(self.tenant, - self.userdisabled, - str(self.auth_token)) - resp_val = int(resp['status']) - content = etree.fromstring(content) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(403, resp_val) - self.assertEqual('application/xml', utils.content_type(resp)) - - def test_user_password_bad_request_json(self): - h = httplib2.Http(".cache") - utils.create_user(self.tenant, self.user, - str(self.auth_token)) - url = '%stenants/%s/users/%s/password' % (URL, self.tenant, self.user) - data = '{"user_bad": { "password": "p@ssword"}}' - resp, content = h.request(url, "PUT", body=data, - headers={"Content-Type": "application/json", - "X-Auth-Token": self.auth_token}) - resp_val = int(resp['status']) - content = json.loads(content) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - utils.delete_user(self.tenant, self.user, str(self.auth_token)) - self.assertEqual(400, resp_val) - - def test_user_password_bad_request_xml(self): - h = httplib2.Http(".cache") - utils.create_user_xml(self.tenant, self.user, str(self.auth_token)) - url = '%stenants/%s/users/%s/password' % (URL, self.tenant, self.user) - data = ' \ - user xmlns="http://docs.openstack.org/identity/api/v2.0" \ - password="p@ssword" />' - resp, content = h.request(url, "PUT", body=data, - headers={"Content-Type": "application/xml", - "X-Auth-Token": self.auth_token, - "ACCEPT": "application/xml"}) - resp_val = int(resp['status']) - content = etree.fromstring(content) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - utils.delete_user(self.tenant, self.user, str(self.auth_token)) - self.assertEqual(400, resp_val) - self.assertEqual('application/xml', utils.content_type(resp)) - - def test_user_password_expired_token(self): - utils.create_user(self.tenant, self.user, str(self.auth_token)) - resp, content = utils.user_password_json(self.tenant, - self.user, - str(self.exp_auth_token)) - resp_val = int(resp['status']) - content = json.loads(content) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(403, resp_val) - - def test_user_password_expired_token_xml(self): - utils.create_user(self.tenant, self.user, str(self.auth_token)) - resp, content = utils.user_password_xml(self.tenant, - self.user, - str(self.exp_auth_token)) - resp_val = int(resp['status']) - content = etree.fromstring(content) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(403, resp_val) - self.assertEqual('application/xml', utils.content_type(resp)) - - def test_user_password_disabled_token(self): - utils.create_user(self.tenant, self.user, str(self.auth_token)) - resp, content = utils.user_password_json(self.tenant, - self.user, - str(self.disabled_token)) - resp_val = int(resp['status']) - content = json.loads(content) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(403, resp_val) - - def test_user_password_disabled_token_xml(self): - utils.create_user(self.tenant, self.user, str(self.auth_token)) - resp, content = utils.user_password_xml(self.tenant, - self.user, - str(self.disabled_token)) - resp_val = int(resp['status']) - content = etree.fromstring(content) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(403, resp_val) - self.assertEqual('application/xml', utils.content_type(resp)) - - def test_user_password_invalid_token(self): - utils.create_user(self.tenant, - self.user, - str(self.auth_token)) - resp, content = utils.user_password_json(self.tenant, - self.user, - str(self.invalid_token)) - resp_val = int(resp['status']) - content = json.loads(content) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(404, resp_val) - - def test_user_password_invalid_token_xml(self): - utils.create_user(self.tenant, self.user, str(self.auth_token)) - resp, content = utils.user_password_xml(self.tenant, - self.user, - str(self.invalid_token)) - resp_val = int(resp['status']) - content = etree.fromstring(content) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(404, resp_val) - self.assertEqual('application/xml', utils.content_type(resp)) - - def test_user_password_missing_token(self): - utils.create_user(self.tenant, self.user, str(self.auth_token)) - resp, content = utils.user_password_json(self.tenant, - self.user, - str(self.missing_token)) - resp_val = int(resp['status']) - content = json.loads(content) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(401, resp_val) - - def test_user_password_missing_token_xml(self): - utils.create_user(self.tenant, self.user, str(self.auth_token)) - resp, content = utils.user_password_xml(self.tenant, - self.user, - str(self.missing_token)) - resp_val = int(resp['status']) - content = etree.fromstring(content) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(401, resp_val) - self.assertEqual('application/xml', utils.content_type(resp)) - - -class SetEnabledTest(UserTest): - - def test_user_enabled(self): - utils.create_user(self.tenant, self.user, str(self.auth_token)) - resp, content = utils.user_enabled_json(self.tenant, - self.user, - str(self.auth_token)) - resp_val = int(resp['status']) - content = json.loads(content) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - utils.delete_user(self.tenant, self.user, str(self.auth_token)) - self.assertEqual(200, resp_val) - self.assertEqual(True, content['user']['enabled']) - - def test_user_enabled_xml(self): - utils.create_user(self.tenant, self.user, str(self.auth_token)) - resp, content = utils.user_enabled_xml(self.tenant, - self.user, - str(self.auth_token)) - resp_val = int(resp['status']) - content = etree.fromstring(content) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - utils.delete_user(self.tenant, self.user, str(self.auth_token)) - self.assertEqual(200, resp_val) - self.assertEqual('true', content.get("enabled")) - self.assertEqual('application/xml', utils.content_type(resp)) - - def test_user_enabled_bad_request_json(self): - h = httplib2.Http(".cache") - utils.create_user(self.tenant, self.user, - str(self.auth_token)) - url = '%stenants/%s/users/%s/enabled' % (URL, self.tenant, self.user) - data = '{"user_bad": { "enabled": true}}' - resp, content = h.request(url, "PUT", body=data, - headers={"Content-Type": "application/json", - "X-Auth-Token": self.auth_token}) - resp_val = int(resp['status']) - content = json.loads(content) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - utils.delete_user(self.tenant, self.user, str(self.auth_token)) - self.assertEqual(400, resp_val) - - def test_user_enabled_bad_request_xml(self): - h = httplib2.Http(".cache") - utils.create_user_xml(self.tenant, self.user, - str(self.auth_token)) - url = '%stenants/%s/users/%s/enabled' % (URL, self.tenant, self.user) - data = ' \ - user xmlns="http://docs.openstack.org/identity/api/v2.0" \ - enabled="true" />' - resp, content = h.request(url, "PUT", body=data, - headers={"Content-Type": "application/xml", - "X-Auth-Token": self.auth_token, - "ACCEPT": "application/xml"}) - resp_val = int(resp['status']) - content = etree.fromstring(content) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - utils.delete_user(self.tenant, self.user, str(self.auth_token)) - self.assertEqual(400, resp_val) - self.assertEqual('application/xml', utils.content_type(resp)) - - def test_user_enabled_disabled_tenant(self): - utils.create_user(self.tenant, self.user, str(self.auth_token)) - resp, content = utils.user_enabled_json('0000', - self.user, - str(self.auth_token)) - resp_val = int(resp['status']) - content = json.loads(content) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(403, resp_val) - - def test_user_enabled_disabled_tenant_xml(self): - utils.create_user(self.tenant, self.user, str(self.auth_token)) - resp, content = utils.user_enabled_xml('0000', - self.user, - str(self.auth_token)) - resp_val = int(resp['status']) - content = etree.fromstring(content) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(403, resp_val) - self.assertEqual('application/xml', utils.content_type(resp)) - - def test_user_enabled_expired_token(self): - utils.create_user(self.tenant, self.user, str(self.auth_token)) - resp, content = utils.user_enabled_json(self.tenant, - self.user, - str(self.exp_auth_token)) - resp_val = int(resp['status']) - content = json.loads(content) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(403, resp_val) - - def test_user_enabled_expired_token_xml(self): - utils.create_user(self.tenant, self.user, str(self.auth_token)) - resp, content = utils.user_enabled_xml(self.tenant, - self.user, - str(self.exp_auth_token)) - resp_val = int(resp['status']) - content = etree.fromstring(content) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(403, resp_val) - self.assertEqual('application/xml', utils.content_type(resp)) - - def test_user_enabled_disabled_token(self): - utils.create_user(self.tenant, self.user, str(self.auth_token)) - resp, content = utils.user_enabled_json(self.tenant, - self.user, - str(self.disabled_token)) - resp_val = int(resp['status']) - content = json.loads(content) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(403, resp_val) - - def test_user_enabled_disabled_token_xml(self): - utils.create_user(self.tenant, self.user, str(self.auth_token)) - resp, content = utils.user_enabled_xml(self.tenant, - self.user, - str(self.disabled_token)) - resp_val = int(resp['status']) - content = etree.fromstring(content) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(403, resp_val) - self.assertEqual('application/xml', utils.content_type(resp)) - - def test_user_enabled_invalid_token(self): - utils.create_user(self.tenant, self.user, str(self.auth_token)) - resp, content = utils.user_enabled_json(self.tenant, - self.user, - str(self.invalid_token)) - resp_val = int(resp['status']) - content = json.loads(content) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(404, resp_val) - - def test_user_enabled_invalid_token_xml(self): - utils.create_user(self.tenant, self.user, str(self.auth_token)) - resp, content = utils.user_enabled_xml(self.tenant, - self.user, - str(self.invalid_token)) - resp_val = int(resp['status']) - content = etree.fromstring(content) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(404, resp_val) - self.assertEqual('application/xml', utils.content_type(resp)) - - def test_user_enabled_missing_token(self): - utils.create_user(self.tenant, self.user, str(self.auth_token)) - resp, content = utils.user_enabled_json(self.tenant, - self.user, - str(self.missing_token)) - resp_val = int(resp['status']) - content = json.loads(content) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(401, resp_val) - - def test_user_enabled_missing_token_xml(self): - utils.create_user(self.tenant, self.user, str(self.auth_token)) - resp, content = utils.user_enabled_xml(self.tenant, - self.user, - str(self.missing_token)) - resp_val = int(resp['status']) - content = etree.fromstring(content) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(401, resp_val) - self.assertEqual('application/xml', utils.content_type(resp)) - - -class AddUserTest(UserTest): - - def setUp(self): - self.token = utils.get_token('joeuser1', 'secrete', '1234') - self.tenant = utils.get_another_tenant() - self.password = utils.get_password() - self.email = utils.get_email() - self.user = 'joeuser1' - self.userdisabled = utils.get_userdisabled() - self.auth_token = utils.get_auth_token() - self.exp_auth_token = utils.get_exp_auth_token() - self.disabled_token = utils.get_disabled_token() - self.missing_token = utils.get_none_token() - self.invalid_token = utils.get_non_existing_token() - - def tearDown(self): - utils.delete_user(self.tenant, self.user, str(self.auth_token)) - utils.delete_tenant(self.tenant, str(self.auth_token)) - - def test_add_user_tenant(self): - utils.create_tenant(self.tenant, str(self.auth_token)) - resp, content = utils.create_user(self.tenant, - self.user, - str(self.auth_token)) - resp_val = int(resp['status']) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(201, resp_val) - - def test_add_user_tenant_xml(self): - utils.create_tenant(self.tenant, str(self.auth_token)) - resp, content = utils.create_user_xml(self.tenant, - self.user, - str(self.auth_token)) - resp_val = int(resp['status']) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(201, resp_val) - - def test_add_user_tenant_conflict(self): - utils.create_tenant(self.tenant, str(self.auth_token)) - utils.create_user(self.tenant, self.user, str(self.auth_token)) - resp, content = utils.create_user(self.tenant, - self.user, - str(self.auth_token)) - - resp_val = int(resp['status']) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(409, resp_val) - - def test_add_user_tenant_conflict_xml(self): - utils.create_tenant(self.tenant, str(self.auth_token)) - utils.create_user_xml(self.tenant, self.user, str(self.auth_token)) - resp, content = utils.create_user_xml(self.tenant, - self.user, - str(self.auth_token)) - resp_val = int(resp['status']) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(409, resp_val) - - - def test_add_user_tenant_expired_token(self): - utils.create_tenant(self.tenant, str(self.auth_token)) - resp, content = utils.create_user(self.tenant, - self.user, - str(self.exp_auth_token)) - resp_val = int(resp['status']) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(403, resp_val) - - def test_add_user_tenant_expired_token_xml(self): - utils.create_tenant(self.tenant, str(self.auth_token)) - resp, content = utils.create_user_xml(self.tenant, - self.user, - str(self.exp_auth_token)) - resp_val = int(resp['status']) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(403, resp_val) - - def test_add_user_tenant_disabled_token(self): - utils.create_tenant(self.tenant, str(self.auth_token)) - resp, content = utils.create_user(self.tenant, - self.user, - str(self.disabled_token)) - resp_val = int(resp['status']) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(403, resp_val) - - def test_add_user_tenant_disabled_token_xml(self): - utils.create_tenant(self.tenant, str(self.auth_token)) - resp, content = utils.create_user_xml(self.tenant, - self.user, - str(self.disabled_token)) - resp_val = int(resp['status']) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(403, resp_val) - - def test_add_user_tenant_invalid_token(self): - utils.create_tenant(self.tenant, str(self.auth_token)) - resp, content = utils.create_user(self.tenant, - self.user, - str(self.invalid_token)) - resp_val = int(resp['status']) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(404, resp_val) - - def test_add_user_tenant_invalid_token_xml(self): - utils.create_tenant(self.tenant, str(self.auth_token)) - resp, content = utils.create_user_xml(self.tenant, - self.user, - str(self.invalid_token)) - resp_val = int(resp['status']) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(404, resp_val) - - def test_add_user_tenant_missing_token(self): - utils.create_tenant(self.tenant, str(self.auth_token)) - resp, content = utils.create_user(self.tenant, - self.user, - str(self.missing_token)) - resp_val = int(resp['status']) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(401, resp_val) - - def test_add_user_tenant_missing_token_xml(self): - utils.create_tenant(self.tenant, str(self.auth_token)) - resp, content = utils.create_user_xml(self.tenant, - self.user, - str(self.missing_token)) - resp_val = int(resp['status']) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(401, resp_val) - - def test_add_user_tenant_disabled_tenant(self): - utils.create_tenant(self.tenant, str(self.auth_token)) - resp, content = utils.create_user('0000', - self.user, - str(self.auth_token)) - resp_val = int(resp['status']) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(403, resp_val) - - def test_add_user_tenant_disabled_tenant_xml(self): - utils.create_tenant(self.tenant, str(self.auth_token)) - resp, content = utils.create_user_xml('0000', - self.user, - str(self.auth_token)) - resp_val = int(resp['status']) - if resp_val == 500: - self.fail('Identity Fault') - elif resp_val == 503: - self.fail('Service Not Available') - self.assertEqual(403, resp_val) - -if __name__ == '__main__': - unittest.main() diff --git a/test/unit/test_version.py b/test/unit/test_version.py deleted file mode 100644 index 3e98935e..00000000 --- a/test/unit/test_version.py +++ /dev/null @@ -1,49 +0,0 @@ -# vim: tabstop=4 shiftwidth=4 softtabstop=4 -# Copyright (c) 2010-2011 OpenStack, LLC. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - - -import httplib2 -import os -import sys -sys.path.append(os.path.abspath(os.path.join(os.path.abspath(__file__), - '..', '..', '..', '..', 'keystone'))) -import unittest - -import test_common as utils - - -class VersionTest(unittest.TestCase): - - #Given _a_ to make inherited test cases in an order. - #here to call below method will call as last test case - - def test_a_get_version_json(self): - header = httplib2.Http(".cache") - resp, content = header.request(utils.URL, "GET", body="", - headers={"Content-Type": "application/json"}) - self.assertEqual(200, int(resp['status'])) - self.assertEqual('application/json', utils.content_type(resp)) - - def test_a_get_version_xml(self): - header = httplib2.Http(".cache") - resp, content = header.request(utils.URL, "GET", body="", - headers={"Content-Type": "application/xml", - "ACCEPT": "application/xml"}) - self.assertEqual(200, int(resp['status'])) - self.assertEqual('application/xml', utils.content_type(resp)) - -if __name__ == '__main__': - unittest.main() diff --git a/tools/management/delgroup.py b/tools/management/delgroup.py deleted file mode 100755 index 1b48cd77..00000000 --- a/tools/management/delgroup.py +++ /dev/null @@ -1,54 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2010-2011 OpenStack, LLC. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import os -import sys - -# If ../keystone/__init__.py exists, add ../ to Python search path, so that -# it will override what happens to be installed in /usr/(local/)lib/python... -possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]), - os.pardir, - os.pardir)) -if os.path.exists(os.path.join(possible_topdir, 'keystone', '__init__.py')): - sys.path.insert(0, possible_topdir) - -import optparse -import keystone.db.sqlalchemy.api as db_api - - -def main(): - usage = "usage: %prog group_id" - parser = optparse.OptionParser(usage) - options, args = parser.parse_args() - if len(args) != 1: - parser.error("Incorrect number of arguments") - else: - index = args[0] - - try: - o = db_api.group_get(index) - if o == None: - raise IndexError("Group %s not found", index) - else: - db_api.group_delete(index) - print 'Group', index, 'deleted.' - - except Exception, e: - print 'Error deleting group', index, str(e) - - -if __name__ == '__main__': - main() diff --git a/tools/management/getgroup.py b/tools/management/getgroup.py deleted file mode 100755 index 9bb0e41f..00000000 --- a/tools/management/getgroup.py +++ /dev/null @@ -1,52 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2010-2011 OpenStack, LLC. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import os -import sys - -# If ../keystone/__init__.py exists, add ../ to Python search path, so that -# it will override what happens to be installed in /usr/(local/)lib/python... -possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]), - os.pardir, - os.pardir)) -if os.path.exists(os.path.join(possible_topdir, 'keystone', '__init__.py')): - sys.path.insert(0, possible_topdir) - -import optparse -import keystone.db.sqlalchemy.api as db_api - - -def main(): - usage = "usage: %prog group_id" - parser = optparse.OptionParser(usage) - options, args = parser.parse_args() - if len(args) != 1: - parser.error("Incorrect number of arguments") - else: - index = args[0] - - try: - o = db_api.group_get(index) - if o == None: - raise IndexError("Group %s not found", index) - - print o.id, o.desc - except Exception, e: - print 'Error getting group', index, str(e) - - -if __name__ == '__main__': - main() diff --git a/tools/management/getgroups.py b/tools/management/getgroups.py deleted file mode 100755 index 2fc94cb9..00000000 --- a/tools/management/getgroups.py +++ /dev/null @@ -1,49 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2010-2011 OpenStack, LLC. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import os -import sys - -# If ../keystone/__init__.py exists, add ../ to Python search path, so that -# it will override what happens to be installed in /usr/(local/)lib/python... -possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]), - os.pardir, - os.pardir)) -if os.path.exists(os.path.join(possible_topdir, 'keystone', '__init__.py')): - sys.path.insert(0, possible_topdir) - -import optparse -import keystone.db.sqlalchemy.api as db_api - - -def main(): - usage = "usage: %prog " - parser = optparse.OptionParser(usage) - options, args = parser.parse_args() - if len(args) != 0: - parser.error("Incorrect number of arguments") - else: - try: - u = db_api.group_get_all() - if u == None: - raise IndexError("Groups not found") - for row in u: - print row.id - except Exception, e: - print 'Error getting groups:', str(e) - -if __name__ == '__main__': - main() diff --git a/tools/management/getgroupusers.py b/tools/management/getgroupusers.py deleted file mode 100755 index 1d663eb4..00000000 --- a/tools/management/getgroupusers.py +++ /dev/null @@ -1,51 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2010-2011 OpenStack, LLC. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import os -import sys - -# If ../keystone/__init__.py exists, add ../ to Python search path, so that -# it will override what happens to be installed in /usr/(local/)lib/python... -possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]), - os.pardir, - os.pardir)) -if os.path.exists(os.path.join(possible_topdir, 'keystone', '__init__.py')): - sys.path.insert(0, possible_topdir) - -import optparse -import keystone.db.sqlalchemy.api as db_api - - -def main(): - usage = "usage: %prog group_id" - parser = optparse.OptionParser(usage) - options, args = parser.parse_args() - if len(args) != 1: - parser.error("Incorrect number of arguments") - else: - group_id = args[0] - - try: - g = db_api.group_users(group_id) - if g == None: - raise IndexError("Group users not found") - for row in g: - print row - except Exception, e: - print 'Error getting group users for group', group_id, ':', str(e) - -if __name__ == '__main__': - main() diff --git a/tools/management/getuser.py b/tools/management/getuser.py deleted file mode 100755 index af0ba89f..00000000 --- a/tools/management/getuser.py +++ /dev/null @@ -1,49 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2010-2011 OpenStack, LLC. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import os -import sys - -# If ../keystone/__init__.py exists, add ../ to Python search path, so that -# it will override what happens to be installed in /usr/(local/)lib/python... -possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]), - os.pardir, - os.pardir)) -if os.path.exists(os.path.join(possible_topdir, 'keystone', '__init__.py')): - sys.path.insert(0, possible_topdir) - -import optparse -import keystone.db.sqlalchemy.api as db_api - - -def main(): - usage = "usage: %prog username" - parser = optparse.OptionParser(usage) - options, args = parser.parse_args() - if len(args) != 1: - parser.error("Incorrect number of arguments") - else: - username = args[0] - try: - u = db_api.user_get(username) - if u == None: - raise IndexError("User not found") - print u.id, u.email, u.enabled - except Exception, e: - print 'Error finding user', username, ':', str(e) - -if __name__ == '__main__': - main() diff --git a/tools/management/getusergroups.py b/tools/management/getusergroups.py deleted file mode 100755 index 33801a93..00000000 --- a/tools/management/getusergroups.py +++ /dev/null @@ -1,50 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2010-2011 OpenStack, LLC. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import os -import sys - -# If ../keystone/__init__.py exists, add ../ to Python search path, so that -# it will override what happens to be installed in /usr/(local/)lib/python... -possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]), - os.pardir, - os.pardir)) -if os.path.exists(os.path.join(possible_topdir, 'keystone', '__init__.py')): - sys.path.insert(0, possible_topdir) - -import optparse -import keystone.db.sqlalchemy.api as db_api - - -def main(): - usage = "usage: %prog user_id" - parser = optparse.OptionParser(usage) - options, args = parser.parse_args() - if len(args) != 1: - parser.error("Incorrect number of arguments") - else: - username = args[0] - try: - g = db_api.user_groups(username) - if g == None: - raise IndexError("User groups not found") - for row in g: - print row - except Exception, e: - print 'Error getting user groups for user', user_id, ':', str(e) - -if __name__ == '__main__': - main() diff --git a/tools/management/groupadd.py b/tools/management/groupadd.py deleted file mode 100755 index 11329e44..00000000 --- a/tools/management/groupadd.py +++ /dev/null @@ -1,52 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2010-2011 OpenStack, LLC. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import os -import sys - -# If ../keystone/__init__.py exists, add ../ to Python search path, so that -# it will override what happens to be installed in /usr/(local/)lib/python... -possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]), - os.pardir, - os.pardir)) -if os.path.exists(os.path.join(possible_topdir, 'keystone', '__init__.py')): - sys.path.insert(0, possible_topdir) - -import optparse -import keystone.db.sqlalchemy.api as db_api -from keystone.db.sqlalchemy import models - - -def main(): - usage = "usage: %prog group_id group_desc" - parser = optparse.OptionParser(usage) - options, args = parser.parse_args() - if len(args) != 2: - parser.error("Incorrect number of arguments") - else: - group_id = args[0] - group_desc = args[1] - try: - g = models.Group() - g.id = group_id - g.desc = group_desc - db_api.group_create(g) - print 'Group', g.id, 'created.' - except Exception, e: - print 'Error creating group', group_id, ':', str(e) - -if __name__ == '__main__': - main() diff --git a/tools/management/setuserlock.py b/tools/management/setuserlock.py deleted file mode 100755 index 7cfa8c15..00000000 --- a/tools/management/setuserlock.py +++ /dev/null @@ -1,61 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2010-2011 OpenStack, LLC. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import os -import sys - -# If ../keystone/__init__.py exists, add ../ to Python search path, so that -# it will override what happens to be installed in /usr/(local/)lib/python... -possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]), - os.pardir, - os.pardir)) -if os.path.exists(os.path.join(possible_topdir, 'keystone', '__init__.py')): - sys.path.insert(0, possible_topdir) - -import optparse -import keystone.db.sqlalchemy.api as db_api - - -def main(): - usage = "usage: %prog username enabled" - parser = optparse.OptionParser(usage) - options, args = parser.parse_args() - if len(args) != 2: - parser.error("Incorrect number of arguments") - else: - username = args[0] - enabled = args[1].capitalize().strip() - - if enabled == 'True' or enabled == '1': - enabled = 1 - elif enabled == 'False' or enabled == '0': - enabled = 0 - else: - parser.error("Incorrect arguments value") - - try: - u = db_api.user_get(username) - if u == None: - raise IndexError("User not found") - else: - values = {'enabled': enabled} - db_api.user_update(username, values) - print 'User', u.id, 'updated. Enabled =', enabled - except Exception, e: - print 'Error updating user', username, ':', str(e) - -if __name__ == '__main__': - main() diff --git a/tools/management/setuserpswd.py b/tools/management/setuserpswd.py deleted file mode 100755 index abfddbda..00000000 --- a/tools/management/setuserpswd.py +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2010-2011 OpenStack, LLC. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import os -import sys - -# If ../keystone/__init__.py exists, add ../ to Python search path, so that -# it will override what happens to be installed in /usr/(local/)lib/python... -possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]), - os.pardir, - os.pardir)) -if os.path.exists(os.path.join(possible_topdir, 'keystone', '__init__.py')): - sys.path.insert(0, possible_topdir) - -import optparse -import keystone.db.sqlalchemy.api as db_api - - -def main(): - usage = "usage: %prog username password" - parser = optparse.OptionParser(usage) - options, args = parser.parse_args() - if len(args) != 2: - parser.error("Incorrect number of arguments") - else: - username = args[0] - password = args[1] - try: - u = db_api.user_get(username) - if u == None: - raise IndexError("User not found") - else: - values = {'password': password} - db_api.user_update(username, values) - print 'User', u.id, 'updated.' - except Exception, e: - print 'Error updating user', username, ':', str(e) - -if __name__ == '__main__': - main() diff --git a/tools/management/updategroup.py b/tools/management/updategroup.py deleted file mode 100755 index 35b4ef66..00000000 --- a/tools/management/updategroup.py +++ /dev/null @@ -1,54 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2010-2011 OpenStack, LLC. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import os -import sys - -# If ../keystone/__init__.py exists, add ../ to Python search path, so that -# it will override what happens to be installed in /usr/(local/)lib/python... -possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]), - os.pardir, - os.pardir)) -if os.path.exists(os.path.join(possible_topdir, 'keystone', '__init__.py')): - sys.path.insert(0, possible_topdir) - -import optparse -import keystone.db.sqlalchemy.api as db_api -from keystone.db.sqlalchemy import models - - -def main(): - usage = "usage: %prog group_id group_desc" - parser = optparse.OptionParser(usage) - options, args = parser.parse_args() - if len(args) != 2: - parser.error("Incorrect number of arguments") - else: - group = args[0] - desc = args[1] - try: - g = db_api.group_get(group) - if g == None: - raise IndexError("Group not found") - else: - values = {'desc': desc} - db_api.group_update(group, values) - print 'Group', g.id, 'updated.' - except Exception, e: - print 'Error updating user', group, ':', str(e) - -if __name__ == '__main__': - main() diff --git a/tools/management/userdel.py b/tools/management/userdel.py deleted file mode 100755 index f76bc632..00000000 --- a/tools/management/userdel.py +++ /dev/null @@ -1,51 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2010-2011 OpenStack, LLC. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import os -import sys - -# If ../keystone/__init__.py exists, add ../ to Python search path, so that -# it will override what happens to be installed in /usr/(local/)lib/python... -possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]), - os.pardir, - os.pardir)) -if os.path.exists(os.path.join(possible_topdir, 'keystone', '__init__.py')): - sys.path.insert(0, possible_topdir) - -import optparse -import keystone.db.sqlalchemy.api as db_api - - -def main(): - usage = "usage: %prog username" - parser = optparse.OptionParser(usage) - options, args = parser.parse_args() - if len(args) != 1: - parser.error("Incorrect number of arguments") - else: - username = args[0] - try: - u = db_api.user_get(username) - if u == None: - raise IndexError("User not found") - else: - db_api.user_delete(username) - print 'User', username, 'deleted.' - except Exception, e: - print 'Error deleting user', username, ':', str(e) - -if __name__ == '__main__': - main() diff --git a/tools/management/userupdate.py b/tools/management/userupdate.py deleted file mode 100755 index 5196d681..00000000 --- a/tools/management/userupdate.py +++ /dev/null @@ -1,53 +0,0 @@ -#!/usr/bin/env python -# Copyright (c) 2010-2011 OpenStack, LLC. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or -# implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import os -import sys - -# If ../keystone/__init__.py exists, add ../ to Python search path, so that -# it will override what happens to be installed in /usr/(local/)lib/python... -possible_topdir = os.path.normpath(os.path.join(os.path.abspath(sys.argv[0]), - os.pardir, - os.pardir)) -if os.path.exists(os.path.join(possible_topdir, 'keystone', '__init__.py')): - sys.path.insert(0, possible_topdir) - -import optparse -import keystone.db.sqlalchemy.api as db_api - - -def main(): - usage = "usage: %prog username email" - parser = optparse.OptionParser(usage) - options, args = parser.parse_args() - if len(args) != 2: - parser.error("Incorrect number of arguments") - else: - username = args[0] - email = args[1] - try: - u = db_api.user_get(username) - if u == None: - raise IndexError("User not found") - else: - values = {'email': email} - db_api.user_update(username, values) - print 'User', u.id, 'updated.' - except Exception, e: - print 'Error updating user', username, ':', str(e) - -if __name__ == '__main__': - main() -- cgit From 60db3cbba4c9c560206977bf7791e3682c0186ba Mon Sep 17 00:00:00 2001 From: Ziad Sawalha Date: Sat, 11 Jun 2011 16:04:34 -0500 Subject: Forgot to add doc file --- docs/guide/src/docbkx/samples/tenants-request.txt | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 docs/guide/src/docbkx/samples/tenants-request.txt diff --git a/docs/guide/src/docbkx/samples/tenants-request.txt b/docs/guide/src/docbkx/samples/tenants-request.txt new file mode 100644 index 00000000..9dbf85e5 --- /dev/null +++ b/docs/guide/src/docbkx/samples/tenants-request.txt @@ -0,0 +1,5 @@ +GET /v2.0/tenants HTTP/1.1 +Host: identity.api.openstack.org +Content-Type: application/json +X-Auth-Token: fa8426a0-8eaf-4d22-8e13-7c1b16a9370c +Accept: application/json \ No newline at end of file -- cgit From f3a9d9ab933967b94ece010ca6c2aa5262303764 Mon Sep 17 00:00:00 2001 From: Ziad Sawalha Date: Sat, 11 Jun 2011 16:05:16 -0500 Subject: Readd test folder --- keystone/test/EchoSOAPUI.xml | 2 + keystone/test/IdentitySOAPUI.xml | 1355 ++++++++++++++++++++++++ keystone/test/__init__.py | 0 keystone/test/functional/base.py | 77 ++ keystone/test/functional/ksapi.py | 146 +++ keystone/test/functional/run_tests.py | 61 ++ keystone/test/functional/sample_test.py | 85 ++ keystone/test/functional/simplerest.py | 641 ++++++++++++ keystone/test/functional/test_tokens.py | 51 + keystone/test/unit/__init__.py | 0 keystone/test/unit/base.py | 282 +++++ keystone/test/unit/decorators.py | 49 + keystone/test/unit/test_BaseURLs.py | 667 ++++++++++++ keystone/test/unit/test_auth.py | 34 + keystone/test/unit/test_authentication.py | 215 ++++ keystone/test/unit/test_authn_v2.py | 463 +++++++++ keystone/test/unit/test_common.py | 809 +++++++++++++++ keystone/test/unit/test_exthandler.py | 65 ++ keystone/test/unit/test_groups.py | 966 ++++++++++++++++++ keystone/test/unit/test_keystone.py | 60 ++ keystone/test/unit/test_roles.py | 682 +++++++++++++ keystone/test/unit/test_server.py | 86 ++ keystone/test/unit/test_tenant_groups.py | 1217 ++++++++++++++++++++++ keystone/test/unit/test_tenants.py | 661 ++++++++++++ keystone/test/unit/test_token.py | 173 ++++ keystone/test/unit/test_users.py | 1584 +++++++++++++++++++++++++++++ keystone/test/unit/test_version.py | 49 + 27 files changed, 10480 insertions(+) create mode 100644 keystone/test/EchoSOAPUI.xml create mode 100644 keystone/test/IdentitySOAPUI.xml create mode 100644 keystone/test/__init__.py create mode 100644 keystone/test/functional/base.py create mode 100644 keystone/test/functional/ksapi.py create mode 100755 keystone/test/functional/run_tests.py create mode 100644 keystone/test/functional/sample_test.py create mode 100644 keystone/test/functional/simplerest.py create mode 100644 keystone/test/functional/test_tokens.py create mode 100644 keystone/test/unit/__init__.py create mode 100644 keystone/test/unit/base.py create mode 100644 keystone/test/unit/decorators.py create mode 100644 keystone/test/unit/test_BaseURLs.py create mode 100644 keystone/test/unit/test_auth.py create mode 100755 keystone/test/unit/test_authentication.py create mode 100644 keystone/test/unit/test_authn_v2.py create mode 100755 keystone/test/unit/test_common.py create mode 100644 keystone/test/unit/test_exthandler.py create mode 100644 keystone/test/unit/test_groups.py create mode 100644 keystone/test/unit/test_keystone.py create mode 100644 keystone/test/unit/test_roles.py create mode 100644 keystone/test/unit/test_server.py create mode 100644 keystone/test/unit/test_tenant_groups.py create mode 100644 keystone/test/unit/test_tenants.py create mode 100644 keystone/test/unit/test_token.py create mode 100644 keystone/test/unit/test_users.py create mode 100644 keystone/test/unit/test_version.py diff --git a/keystone/test/EchoSOAPUI.xml b/keystone/test/EchoSOAPUI.xml new file mode 100644 index 00000000..8a74eee0 --- /dev/null +++ b/keystone/test/EchoSOAPUI.xml @@ -0,0 +1,2 @@ + +http://localhost:8090X-Auth-TokenHEADERxs:string*/*application/xml200v1:echoapplication/json200<xml-fragment/>http://localhost:8090*/*application/xml200v1:echoapplication/json200http://localhost:8090*/*application/xml200v1:echoapplication/json200http://localhost:8090*/*application/xml200v1:echoapplication/json200http://localhost:8090*/*application/xml200v1:echoapplication/json200http://localhost:8090*/*application/xml200v1:echoapplication/json200http://localhost:8090 \ No newline at end of file diff --git a/keystone/test/IdentitySOAPUI.xml b/keystone/test/IdentitySOAPUI.xml new file mode 100644 index 00000000..3cf2984e --- /dev/null +++ b/keystone/test/IdentitySOAPUI.xml @@ -0,0 +1,1355 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +]]>file:/Users/jorgew/projects/keystone/keystone/identity.wadl + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +]]>http://wadl.dev.java.net/2009/02file:/Users/jorgew/projects/keystone/keystone/xsd/api.xsd<schema elementFormDefault="qualified" attributeFormDefault="unqualified" targetNamespace="http://docs.openstack.org/identity/api/v2.0" xmlns="http://www.w3.org/2001/XMLSchema" xmlns:identity="http://docs.openstack.org/identity/api/v2.0" xmlns:xsd="http://www.w3.org/2001/XMLSchema"> + <include schemaLocation="token.xsd"/> + <include schemaLocation="tenant.xsd"/> + <include schemaLocation="fault.xsd"/> +</schema>http://www.w3.org/2001/XMLSchemafile:/Users/jorgew/projects/keystone/keystone/xsd/token.xsd + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +]]>http://www.w3.org/2001/XMLSchemafile:/Users/jorgew/projects/keystone/keystone/xsd/tenant.xsd + + + + + + + + + + + + + + + + + + + + + + + +]]>http://www.w3.org/2001/XMLSchemafile:/Users/jorgew/projects/keystone/keystone/xsd/atom/atom.xsd + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + See section 3.4 of the ATOM RFC + RFC4287 + + + + + + + TODO + + + + + + + TODO + + + + + + + TODO + + + + + + + TODO + + + + + + + TODO + + + + + + +]]>http://www.w3.org/2001/XMLSchemafile:/Users/jorgew/projects/keystone/keystone/xsd/atom/xml.xsd + + + +
+

About the XML namespace

+
+

This schema document describes the XML namespace, in a form + suitable for import by other schema documents.

+

+ See + http://www.w3.org/XML/1998/namespace.html + and + http://www.w3.org/TR/REC-xml + for information + about this namespace. +

+

Note that local names in this namespace are intended to be + defined only by the World Wide Web Consortium or its subgroups. + The names currently defined in this namespace are listed below. + They should not be used with conflicting semantics by any Working + Group, specification, or document instance.

+

+ See further below in this document for more information about + how to refer to this schema document from your own + XSD schema documents + and about + the + namespace-versioning policy governing this schema document + . +

+
+
+
+
+ + + +
+

lang (as an attribute name)

+

denotes an attribute whose value + is a language code for the natural language of the content of + any element; its value is inherited. This name is reserved + by virtue of its definition in the XML specification.

+
+
+

Notes

+

Attempting to install the relevant ISO 2- and 3-letter + codes as the enumerated possible values is probably never + going to be a realistic possibility.

+

+ See BCP 47 at + http://www.rfc-editor.org/rfc/bcp/bcp47.txt + and the IANA language subtag registry at + http://www.iana.org/assignments/language-subtag-registry + for further information. +

+

The union allows for the 'un-declaration' of xml:lang with + the empty string.

+
+
+
+ + + + + + + + + +
+ + + +
+

space (as an attribute name)

+

denotes an attribute whose + value is a keyword indicating what whitespace processing + discipline is intended for the content of the element; its + value is inherited. This name is reserved by virtue of its + definition in the XML specification.

+
+
+
+ + + + + + +
+ + + +
+

base (as an attribute name)

+

denotes an attribute whose value + provides a URI to be used as the base for interpreting any + relative URIs in the scope of the element on which it + appears; its value is inherited. This name is reserved + by virtue of its definition in the XML Base specification.

+

+ See + http://www.w3.org/TR/xmlbase/ + for information about this attribute. +

+
+
+
+
+ + + +
+

id (as an attribute name)

+

denotes an attribute whose value + should be interpreted as if declared to be of type ID. + This name is reserved by virtue of its definition in the + xml:id specification.

+

+ See + http://www.w3.org/TR/xml-id/ + for information about this attribute. +

+
+
+
+
+ + + + + + + + +
+

Father (in any context at all)

+
+

denotes Jon Bosak, the chair of + the original XML Working Group. This name is reserved by + the following decision of the W3C XML Plenary and + XML Coordination groups:

+
+

In appreciation for his vision, leadership and + dedication the W3C XML Plenary on this 10th day of + February, 2000, reserves for Jon Bosak in perpetuity + the XML name "xml:Father".

+
+
+
+
+
+ + +
+

+ About this schema document +

+
+

+ This schema defines attributes and an attribute group suitable + for use by schemas wishing to allow + xml:base + , + xml:lang + , + xml:space + or + xml:id + attributes on elements they define. +

+

To enable this, such a schema must import this schema for + the XML namespace, e.g. as follows:

+
<schema . . .>
+           . . .
+           <import namespace="http://www.w3.org/XML/1998/namespace"
+                      schemaLocation="http://www.w3.org/2001/xml.xsd"/>
+

or

+
<import namespace="http://www.w3.org/XML/1998/namespace"
+                      schemaLocation="http://www.w3.org/2009/01/xml.xsd"/>
+

Subsequently, qualified reference to any of the attributes or the + group defined below will have the desired effect, e.g.

+
<type . . .>
+           . . .
+           <attributeGroup ref="xml:specialAttrs"/>
+

will define a type which will schema-validate an instance element + with any of those attributes.

+
+
+
+
+ + +
+

+ Versioning policy for this schema document +

+
+

+ In keeping with the XML Schema WG's standard versioning + policy, this schema document will persist at + http://www.w3.org/2009/01/xml.xsd + . +

+

+ At the date of issue it can also be found at + http://www.w3.org/2001/xml.xsd + . +

+

+ The schema document at that URI may however change in the future, + in order to remain compatible with the latest version of XML + Schema itself, or with the XML namespace itself. In other words, + if the XML Schema or XML namespaces change, the version of this + document at + http://www.w3.org/2001/xml.xsd + will change accordingly; the version at + http://www.w3.org/2009/01/xml.xsd + will not change. +

+

Previous dated (and unchanging) versions of this schema + document are at:

+ +
+
+
+
+
]]>
http://www.w3.org/2001/XMLSchema
file:/Users/jorgew/projects/keystone/keystone/xsd/fault.xsd + + + + + + + + + + + + + + + + +

A human readable message that is appropriate for display + to the end user.

+
+
+
+ + + +

The optional <details> element may contain useful + information for tracking down errors (e.g a stack + trace). This information may or may not be appropriate + for display to an end user.

+
+
+
+ +
+ + + +

The HTTP status code associated with the current fault.

+
+
+
+ +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +

An optional dateTime denoting when an operation should + be retried.

+
+
+
+
+
+
+]]>
http://www.w3.org/2001/XMLSchema
file:/Users/jorgew/projects/keystone/keystone/xsd/api-common.xsd + + + + + Open Stack Common API Schema Types 1.0 + + + + + +

This is the main index XML Schema document + for Common API Schema Types Version 1.0.

+
+
+ + + +

Types related to extensions.

+
+
+
+ + + +

Types related to API version details.

+
+
+
+
]]>
http://www.w3.org/2001/XMLSchema
file:/Users/jorgew/projects/keystone/keystone/xsd/extensions.xsd + + + + + + + + + + + + + + + + + + + + + + + + + +

There should be at least one atom link + with a describedby relation.

+
+
+
+
+ + + + + +]]>
http://www.w3.org/2001/XMLSchema
file:/Users/jorgew/projects/keystone/keystone/xsd/version.xsd + + + + + + + + + + + + + The VersionStatus type describes a service's operational status. + + + + + + + + + + + + + A version choice list outlines a collection of service version choices. + + + + + + + + + + + In version lists, every single version must + contain at least one self link. + + + + + + + + + + + When used as a root element, a version choice + must contain at least one describedby link. + + + + + + + + + + A version choice contains relevant information about an available service + that a user can then use to target a specific version of the service. Note + that both the descriptive media types and the atom link references are + not manditory and are offered as message enrichment elements rather + than message requirements. + + + + + + + + + + + The ID of a version choice represents the service version's unique + identifier. This ID is guaranteed to be unique only among the + service version choices outlined in the VersionChoiceList. + + + + + + + A version choice's status describes the current operational state of + the given service version. The operational status is captured in a + simple type enumeration called VersionStatus. + + + + + + + + A version choice's updated attribute describes + the time when the version was updated. The + time should be updated anytime + anything + in the + version has changed: documentation, + extensions, bug fixes. + + + + + + + + + + A MediaTypeList outlines a collection of valid media types for a given + service version. + + + + + + + + + + + + A MediaType describes what content types the service version understands. + + + + + + + + + The base of a given media type describes the simple MIME type + that then a more complicated media type can be derived from. These + types are basic and provide no namespace or version specific + data are are only provided as a convenience. Because of this the + base attribute is declared as optional. + + + + + + + + The type attribute of a MediaType describes the MIME specific + identifier of the media type in question. This identifier should include + a vendor namespace ( + See RFC 2048 + ) + as well as a version suffix. + + + + + + +]]>http://www.w3.org/2001/XMLSchema
http://localhost:8080aliasTEMPLATExs:stringapplication/xml200 203v1:extensionapplication/json200 203application/xml400v1:badRequestapplication/xml404v1:itemNotFoundapplication/xml500v1:identityFaultapplication/xml503v1:serviceUnavailableapplication/json400 404 500 503<xml-fragment/>http://localhost:8080application/xml200 203v1:extensionsapplication/json200 203application/xml400v1:badRequestapplication/xml500v1:identityFaultapplication/xml503v1:serviceUnavailableapplication/json400 500 503<xml-fragment/>http://localhost:8080X-Auth-TokenHEADERxs:stringtokenIdTEMPLATExs:stringbelongsToQUERYxs:stringapplication/xml200 203v1:authapplication/json200 203application/xml401v1:unauthorizedapplication/xml403v1:forbiddenapplication/xml403v1:userDisabledapplication/xml400v1:badRequestapplication/xml404v1:itemNotFoundapplication/xml500v1:identityFaultapplication/xml503v1:serviceUnavailableapplication/json400 401 403 404 500 503<xml-fragment/>http://localhost:8080 + + + +application/xml401v1:unauthorizedapplication/xml403v1:forbiddenapplication/xml400v1:badRequestapplication/xml404v1:itemNotFoundapplication/xml500v1:identityFaultapplication/xml503v1:serviceUnavailableapplication/json400 401 403 404 500 503<xml-fragment/>http://localhost:8080 + + +application/xmlv1:passwordCredentialsapplication/jsonapplication/xml200 +203v1:authapplication/json200 +203application/xml401v1:unauthorizedapplication/xml403v1:userDisabledapplication/xml400v1:badRequestapplication/xml500v1:identityFaultapplication/xml503v1:serviceUnavailableapplication/json401 +403 400 500 503<xml-fragment/>http://localhost:8080<passwordCredentials +password="secrete" username="joeuser" +xmlns="http://docs.openstack.org/identity/api/v2.0"/>X-Auth-TokenHEADERxs:stringtenantIdTEMPLATExs:stringapplication/xml200 +203v1:tenantapplication/json200 +203application/xml401v1:unauthorizedapplication/xml403v1:forbiddenapplication/xml400v1:badRequestapplication/xml404v1:itemNotFoundapplication/xml500v1:identityFaultapplication/xml503v1:serviceUnavailableapplication/json400 +401 403 404 500 503<xml-fragment/>http://localhost:8080 + + +application/xmlv1:tenantapplication/jsonapplication/xml200v1:tenantapplication/json200application/xml401v1:unauthorizedapplication/xml403v1:forbiddenapplication/xml404v1:itemNotFoundapplication/xml400v1:badRequestapplication/xml500v1:identityFaultapplication/xml503v1:serviceUnavailableapplication/json401 +403 404 400 500 503<xml-fragment/>http://localhost:8080<v1:tenant enabled="true" xmlns:v1="http://docs.openstack.org/identity/api/v2.0"> + <v1:description>New Description</v1:description> +</v1:tenant> + + +application/xml401v1:unauthorizedapplication/xml403v1:forbiddenapplication/xml400v1:badRequestapplication/xml404v1:itemNotFoundapplication/xml500v1:identityFaultapplication/xml503v1:serviceUnavailableapplication/json400 +401 403 404 500 503<entry key="Accept" value="application/xml" xmlns="http://eviware.com/soapui/config"/>http://localhost:8080 + + +markerQUERYxs:stringlimitQUERYxs:intapplication/xml200 +203v1:tenantsapplication/json200 +203application/xml401v1:unauthorizedapplication/xml403v1:forbiddenapplication/xml400v1:badRequestapplication/xml404v1:itemNotFoundapplication/xml500v1:identityFaultapplication/xml503v1:serviceUnavailableapplication/json400 +401 403 404 500 503<xml-fragment/>http://localhost:8080application/xmlv1:tenantapplication/jsonapplication/xml201v1:tenantapplication/json201application/xml401v1:unauthorizedapplication/xml403v1:forbiddenapplication/xml +409v1:tenantConflictapplication/xml +400v1:badRequestapplication/xml500v1:identityFaultapplication/xml503v1:serviceUnavailableapplication/json401 +403 400 409 500 503<xml-fragment/>http://localhost:8080<v1:tenant +enabled="true" id="my_new_tenant" +xmlns:v1="http://docs.openstack.org/identity/api/v2.0"><v1:description>This +is a description of my tenant. Thank you very +much.</v1:description></v1:tenant>application/xml200 +203v1:versionapplication/json200 +203application/xml400v1:badRequestapplication/xml500v1:identityFaultapplication/xml503v1:serviceUnavailableapplication/json400 +500 503<xml-fragment/>http://localhost:8080
SEQUENTIAL<xml-fragment/>http://localhost:8080authfalsefalsetokenfalsefalseuserfalsefalse + + + +<xml-fragment/>http://localhost:8080unauthorizedfalsefalse401falsefalse + + + +<xml-fragment/>http://localhost:8080unauthorizedfalsefalse401falsefalse + + + +<xml-fragment/>http://localhost:8080unauthorizedfalsefalse401falsefalse + + + +<xml-fragment/>http://localhost:8080forbiddenfalsefalse403falsefalse + + + +<xml-fragment/>http://localhost:8080userDisabledfalsefalse403falsefalse + + + +<xml-fragment/>http://localhost:8080authfalsefalsetokenfalsefalseuserfalsefalse + + + +<xml-fragment/>http://localhost:8080authfalsefalsetokenfalsefalseuserfalsefalse + + +<xml-fragment/>http://localhost:8080itemNotFoundfalsefalse404falsefalse + + + +<xml-fragment/>http://localhost:8080itemNotFoundfalsefalse404falsefalse + + +<xml-fragment/>http://localhost:8080itemNotFoundfalsefalse404falsefalse + + +<xml-fragment/>http://localhost:8080<passwordCredentials password="P@ssword1" username="testuser" xmlns="http://docs.openstack.org/identity/api/v2.0"/>401falsefalseunauthorizedfalsefalse<xml-fragment/>http://localhost:8080<passwordCredentials password="1234" username="disabled" xmlns="http://docs.openstack.org/identity/api/v2.0"/>403falsefalseuserDisabledfalsefalse<xml-fragment/>http://localhost:8080<passwordCredentials password="123774" username="joeuser" xmlns="http://docs.openstack.org/identity/api/v2.0"/>401falsefalseunauthorizedfalsefalse<xml-fragment/>http://localhost:8080<passwordCredentials password="secrete" username="admin" xmlns="http://docs.openstack.org/identity/api/v2.0"/>userfalsefalsetokenfalsefalseAdminfalsefalsedeclare namespace auth='http://docs.openstack.org/identity/api/v2.0'; +/auth:auth/auth:user/auth:groups/auth:group/@id='Admin'truefalsefalse<xml-fragment/>http://localhost:8080<passwordCredentials password="secrete" username="joeuser" xmlns="http://docs.openstack.org/identity/api/v2.0"/>userfalsefalsetokenfalsefalseAdminfalsefalsedeclare namespace auth='http://docs.openstack.org/identity/api/v2.0'; +/auth:auth/auth:user/auth:groups/auth:group/@id='Admin'falsefalsefalse<xml-fragment/>http://localhost:8080{ + "passwordCredentials" : { + "username" : "testuser", + "password" : "P@ssword1" + } +}401falsefalseunauthorizedfalsefalse<xml-fragment/>http://localhost:8080{ + "passwordCredentials" : { + "username" : "disabled", + "password" : "1234" + } +}403falsefalseuserDisabledfalsefalse<xml-fragment/>http://localhost:8080{ + "passwordCredentials" : { + "username" : "joeuser", + "password" : "123774" + } +}401falsefalseunauthorizedfalsefalse<xml-fragment/>http://localhost:8080{ + "passwordCredentials" : { + "username" : "admin", + "password" : "secrete" + } +}userfalsefalsetokenfalsefalseAdminfalsefalse<xml-fragment/>http://localhost:8080{ + "passwordCredentials" : { + "username" : "joeuser", + "password" : "secrete" + } +}userfalsefalsetokenfalsefalseAdminfalsefalse<entry key="Accept" value="application/xml" xmlns="http://eviware.com/soapui/config"/>http://localhost:8080404falsefalseitemNotFoundfalsefalse + + +<xml-fragment/>http://localhost:8080<passwordCredentials password="secrete" username="joeuser" xmlns="http://docs.openstack.org/identity/api/v2.0"/>userfalsefalsetokenfalsefalseAdminfalsefalsedeclare namespace auth='http://docs.openstack.org/identity/api/v2.0'; +/auth:auth/auth:user/auth:groups/auth:group/@id='Admin'falsefalsefalsedeclare namespace auth='http://docs.openstack.org/identity/api/v2.0'; +/auth:auth/auth:token/@id887665443383838falsefalse<entry key="Accept" value="application/xml" xmlns="http://eviware.com/soapui/config"/>http://localhost:8080assert(context.response==null) + + +<xml-fragment/>http://localhost:8080itemNotFoundfalsefalse404falsefalse + + +<xml-fragment/>http://localhost:8080<passwordCredentials password="secrete" username="joeuser" xmlns="http://docs.openstack.org/identity/api/v2.0"/>userfalsefalsetokenfalsefalseAdminfalsefalsedeclare namespace auth='http://docs.openstack.org/identity/api/v2.0'; +/auth:auth/auth:user/auth:groups/auth:group/@id='Admin'falsefalsefalsedeclare namespace auth='http://docs.openstack.org/identity/api/v2.0'; +/auth:auth/auth:token/@id="887665443383838"falsefalsefalse<xml-fragment/>http://localhost:8080<v1:tenant enabled="true" id="my_new_tenant" xmlns:v1="http://docs.openstack.org/identity/api/v2.0"><v1:description>This is a description of my tenant. Thank you very much.</v1:description></v1:tenant>declare namespace ns1='http://docs.openstack.org/identity/api/v2.0'; +/ns1:tenant/@enabled = "true" and /ns1:tenant/@id="my_new_tenant" and /ns1:tenant/ns1:description = "This is a description of my tenant. Thank you very much."truefalsefalse<xml-fragment/>http://localhost:8080<v1:tenant enabled="true" id="my_new_tenant" xmlns:v1="http://docs.openstack.org/identity/api/v2.0"><v1:description>This is a description of my tenant. Thank you very much.</v1:description></v1:tenant>tenantConflictfalsefalse409falsefalse<xml-fragment/>http://localhost:8080<v1:tenant enabled="false" id="mt2" xmlns:v1="http://docs.openstack.org/identity/api/v2.0"><v1:description>New Disabled Tenant</v1:description></v1:tenant>declare namespace ns1='http://docs.openstack.org/identity/api/v2.0'; +/ns1:tenant/@enabled = "false" and /ns1:tenant/@id="mt2" and /ns1:tenant/ns1:description = "New Disabled Tenant"truefalsefalse<xml-fragment/>http://localhost:8080<v1:tenant id="mt3" xmlns:v1="http://docs.openstack.org/identity/api/v2.0"><v1:description>New Tenant 3</v1:description></v1:tenant>declare namespace ns1='http://docs.openstack.org/identity/api/v2.0'; +/ns1:tenant/@id="mt3" and /ns1:tenant/ns1:description = "New Tenant 3"truefalsefalse<xml-fragment/>http://localhost:8080<v1:tenant enabled="true" xmlns:v1="http://docs.openstack.org/identity/api/v2.0"><v1:description>New Tenant No ID</v1:description></v1:tenant>400falsefalsebadRequestfalsefalse<xml-fragment/>http://localhost:8080<v1:tenant enabled="true" id="my_new_tenant" xmlns:v1="http://docs.openstack.org/identity/api/v2.0"></v1:tenant>400falsefalsebadRequestfalsefalse<xml-fragment/>http://localhost:8080{"tenant": + { + "id": "JGroup", + "description": "A description ...", + "enabled": true + } +} +declare namespace ns1='http://localhost/v1.0/tenants'; +ns1:Response/ns1:tenant/ns1:id="JGroup" and ns1:Response/ns1:tenant/ns1:enabled="true" and ns1:Response/ns1:tenant/ns1:description="A description ..."truefalsefalse<xml-fragment/>http://localhost:8080{"tenant": + { + "id": "JGroup", + "description": "A description ...", + "enabled": true + } +}tenantConflictfalsefalse409falsefalse<xml-fragment/>http://localhost:8080{"tenant": + { + "id": "JGroup33", + "description": "A description...", + "enabled": false + } +}declare namespace ns1='http://localhost/v1.0/tenants'; +ns1:Response/ns1:tenant/ns1:id = "JGroup33" and ns1:Response/ns1:tenant/ns1:enabled="false" and ns1:Response/ns1:tenant/ns1:description="A description..."truefalsefalse<xml-fragment/>http://localhost:8080{"tenant": + { + "id": "JGroup65", + "description": "A description..." + } +}declare namespace ns1='http://localhost/v1.0/tenants'; +ns1:Response/ns1:tenant/ns1:id = "JGroup65" and ns1:Response/ns1:tenant/ns1:description = "A description..."truefalsefalse<xml-fragment/>http://localhost:8080{"tenant": + { + "description": "A description...", + "enabled" : true + } +}400falsefalsebadRequestfalsefalse<xml-fragment/>http://localhost:8080{"tenant": + { + "id": "JGroup95", + "enabled": true + } +}400falsefalsebadRequestfalsefalse<xml-fragment/>http://localhost:8080{"tenant": + { + "id": "JGroup95", + "description" : "A description...", + "enabled": "true" + } +}400falsefalsebadRequestfalsefalse<xml-fragment/>http://localhost:8080declare namespace ns1='http://docs.openstack.org/identity/api/v2.0'; +count(//ns1:tenant)8falsefalse<xml-fragment/>http://localhost:8080declare namespace ns1='http://localhost/v1.0/tenants'; +count(//ns1:e)8falsefalse<xml-fragment/>http://localhost:8080declare namespace ns1='http://docs.openstack.org/identity/api/v2.0'; +ns1:tenant/@id1234falsefalsedeclare namespace ns1='http://docs.openstack.org/identity/api/v2.0'; +/ns1:tenant/@enabled and /ns1:tenant/ns1:descriptiontruefalsefalse + + +<xml-fragment/>http://localhost:8080declare namespace ns1='http://localhost/v1.0/tenants/1234'; +ns1:Response/ns1:tenant/ns1:id1234falsefalsedeclare namespace ns1='http://localhost/v1.0/tenants/1234'; +/ns1:Response/ns1:tenant/ns1:enabled and /ns1:Response/ns1:tenant/ns1:descriptiontruefalsefalse + + +<xml-fragment/>http://localhost:8080404falsefalseitemNotFoundfalsefalse + + +<xml-fragment/>http://localhost:8080<v1:tenant enabled="true" id="to_delete" + xmlns:v1="http://docs.openstack.org/identity/api/v2.0"> + <v1:description>To Be Deleted</v1:description> +</v1:tenant>declare namespace ns1='http://docs.openstack.org/identity/api/v2.0'; +/ns1:tenant/@enabled = "true" and /ns1:tenant/@id="to_delete" and /ns1:tenant/ns1:description = "To Be Deleted"truefalsefalse<xml-fragment/>http://localhost:8080declare namespace ns1='http://docs.openstack.org/identity/api/v2.0'; +ns1:tenant/@idto_deletefalsefalsedeclare namespace ns1='http://docs.openstack.org/identity/api/v2.0'; +/ns1:tenant/@enabled and /ns1:tenant/ns1:descriptiontruefalsefalse + + +<entry key="Accept" value="application/xml" xmlns="http://eviware.com/soapui/config"/>http://localhost:8080assert(context.response == null) + + +<xml-fragment/>http://localhost:8080404falsefalseitemNotFoundfalsefalse + + +<entry key="Accept" value="application/xml" xmlns="http://eviware.com/soapui/config"/>http://localhost:8080forbiddenfalsefalse403falsefalse + + +<entry key="Accept" value="application/xml" xmlns="http://eviware.com/soapui/config"/>http://localhost:8080forbiddenfalsefalse403falsefalse + + +<xml-fragment/>http://localhost:8080<v1:tenant enabled="true" id="to_update" xmlns:v1="http://docs.openstack.org/identity/api/v2.0"> + <v1:description>ToUpdate</v1:description> +</v1:tenant>declare namespace ns1='http://docs.openstack.org/identity/api/v2.0'; +/ns1:tenant/@enabled = "true" and /ns1:tenant/@id="to_update" and /ns1:tenant/ns1:description = "ToUpdate"truefalsefalse<xml-fragment/>http://localhost:8080declare namespace ns1='http://docs.openstack.org/identity/api/v2.0'; +/ns1:tenant/@id="to_update" and /ns1:tenant/@enabled = "true" and /ns1:tenant/@id="to_update" and /ns1:tenant/ns1:description = "ToUpdate"truefalsefalse + + +<xml-fragment/>http://localhost:8080<v1:tenant enabled="true" xmlns:v1="http://docs.openstack.org/identity/api/v2.0"> + <v1:description>ToUpdate2</v1:description> +</v1:tenant>declare namespace ns1='http://docs.openstack.org/identity/api/v2.0'; +/ns1:tenant/@id="to_update" and /ns1:tenant/@enabled = "true" and /ns1:tenant/ns1:description = "ToUpdate2"truefalsefalse + + +<xml-fragment/>http://localhost:8080declare namespace ns1='http://docs.openstack.org/identity/api/v2.0'; +/ns1:tenant/@id="to_update" and /ns1:tenant/@enabled = "true" and /ns1:tenant/@id="to_update" and /ns1:tenant/ns1:description = "ToUpdate2"truefalsefalse + + +<xml-fragment/>http://localhost:8080<v1:tenant enabled="false" xmlns:v1="http://docs.openstack.org/identity/api/v2.0"> + <v1:description>ToUpdate2</v1:description> +</v1:tenant>declare namespace ns1='http://docs.openstack.org/identity/api/v2.0'; +/ns1:tenant/@id="to_update" and /ns1:tenant/@enabled = "false" and /ns1:tenant/ns1:description = "ToUpdate2"truefalsefalse + + +<xml-fragment/>http://localhost:8080declare namespace ns1='http://docs.openstack.org/identity/api/v2.0'; +/ns1:tenant/@id="to_update" and /ns1:tenant/@enabled = "false" and /ns1:tenant/@id="to_update" and /ns1:tenant/ns1:description = "ToUpdate2"truefalsefalse + + +<xml-fragment/>http://localhost:8080<v1:tenant id="boogabooga" enabled="false" xmlns:v1="http://docs.openstack.org/identity/api/v2.0"> + <v1:description>ToUpdate2</v1:description> +</v1:tenant>declare namespace ns1='http://docs.openstack.org/identity/api/v2.0'; +/ns1:tenant/@id="to_update" and /ns1:tenant/@enabled = "false" and /ns1:tenant/ns1:description = "ToUpdate2"truefalsefalse + + +<xml-fragment/>http://localhost:8080declare namespace ns1='http://docs.openstack.org/identity/api/v2.0'; +/ns1:tenant/@id="to_update" and /ns1:tenant/@enabled = "false" and /ns1:tenant/@id="to_update" and /ns1:tenant/ns1:description = "ToUpdate2"truefalsefalse + + +<xml-fragment/>http://localhost:8080<v1:tenant enabled="true" xmlns:v1="http://docs.openstack.org/identity/api/v2.0"> + <v1:description>ToUpdate3</v1:description> +</v1:tenant>declare namespace ns1='http://docs.openstack.org/identity/api/v2.0'; +/ns1:tenant/@id="to_update" and /ns1:tenant/@enabled = "true" and /ns1:tenant/ns1:description = "ToUpdate3"truefalsefalse + + +<xml-fragment/>http://localhost:8080declare namespace ns1='http://docs.openstack.org/identity/api/v2.0'; +/ns1:tenant/@id="to_update" and /ns1:tenant/@enabled = "true" and /ns1:tenant/@id="to_update" and /ns1:tenant/ns1:description = "ToUpdate3"truefalsefalse + + +<entry key="Accept" value="application/xml" xmlns="http://eviware.com/soapui/config"/>http://localhost:8080assert(context.response == null) + + +<xml-fragment/>http://localhost:8080declare namespace ns1='http://docs.openstack.org/common/api/v1.0'; +count(/ns1:extensions)1falsefalse<xml-fragment/>http://localhost:8080declare namespace ns1='http://localhost/v1.0/extensions'; +count(//ns1:extensions)1falsefalse<xml-fragment/>http://localhost:8080404falsefalseitemNotFoundfalsefalse<xml-fragment/>http://localhost:8080404falsefalseitemNotFoundfalsefalse<xml-fragment/>http://localhost:8080declare namespace ns1='http://docs.openstack.org/common/api/v1.0'; +count(//ns1:version)1falsefalse<xml-fragment/>http://localhost:8080declare namespace ns1='http://localhost/v1.0'; +count(//ns1:version)1falsefalse
\ No newline at end of file diff --git a/keystone/test/__init__.py b/keystone/test/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/keystone/test/functional/base.py b/keystone/test/functional/base.py new file mode 100644 index 00000000..d30134bc --- /dev/null +++ b/keystone/test/functional/base.py @@ -0,0 +1,77 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 +# Copyright (c) 2011 OpenStack, LLC. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +import dtest + +import ksapi + + +options = None + + +def _get_ksapi(): + """Get an instance of KeystoneAPI20.""" + + # If debug mode has been enabled, let's select a debug stream + dbstream = None + if options.debug: + dbstream = dtest.status + + # Build and return the API object + return ksapi.KeystoneAPI20(options.keystone, dbstream) + + +class BaseKeystoneTest(dtest.DTestCase): + """Base class for Keystone tests.""" + + def setUp(self): + """Initialize tests by setting up a KeystoneAPI20 to call.""" + + # Build the API object + self.ks = _get_ksapi() + + +class KeystoneTest(BaseKeystoneTest): + """Base class for Keystone tests.""" + + token = None + + @classmethod + def setUpClass(cls): + """Initialize tests by setting up a keystone token.""" + + # Get an API object + ks = _get_ksapi() + + # Next, let's authenticate + resp = ks.authenticate(options.username, options.password) + + # Finally, save the authentication token + cls.token = resp.obj['auth']['token']['id'] + + @classmethod + def tearDownClass(cls): + """Revoke the authentication token.""" + + # Get an API object + ks = _get_ksapi() + + # Now, let's revoke the token + resp = ks.revoke_token(cls.token, cls.token) + + # For completeness sake... + cls.token = None diff --git a/keystone/test/functional/ksapi.py b/keystone/test/functional/ksapi.py new file mode 100644 index 00000000..9c426109 --- /dev/null +++ b/keystone/test/functional/ksapi.py @@ -0,0 +1,146 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 +# Copyright (c) 2011 OpenStack, LLC. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +import simplerest + + +class KeystoneAPI20(simplerest.RESTAPI): + get_version_info = simplerest.RESTMethod('get_version_info', 'GET', '/') + + get_extensions = simplerest.RESTMethod('get_extensions', 'GET', + '/extensions') + get_extension = simplerest.RESTMethod('get_extension', 'GET', + '/extensions/{alias}', ['alias']) + + authenticate = simplerest.RESTMethod('authenticate', 'POST', + '/tokens', + ['username', 'password', 'tenantId'], + 'passwordCredentials', + username='req', password='req', + tenantId=('req', False)) + validate_token = simplerest.RESTMethod('validate_token', 'GET', + '/tokens/{tokenId}', + ['x_auth_token', + 'tokenId', 'belongsTo'], + x_auth_token='header', + belongsTo='query') + revoke_token = simplerest.RESTMethod('revoke_token', 'DELETE', + '/tokens/{tokenId}', + ['x_auth_token', 'tokenId'], + x_auth_token='header') + + create_tenant = simplerest.RESTMethod('create_tenant', 'POST', '/tenants', + ['x_auth_token', 'id', + 'description', 'enabled'], + 'tenant', + x_auth_token='header', + id='req', description='req', + enabled='req') + get_tenants = simplerest.RESTMethod('get_tenants', 'GET', '/tenants', + ['x_auth_token'], + x_auth_token='header') + get_tenant = simplerest.RESTMethod('get_tenant', 'GET', + '/tenants/{tenantId}', + ['x_auth_token', 'tenantId'], + x_auth_token='header') + update_tenant = simplerest.RESTMethod('update_tenant', 'PUT', + '/tenants/{tenantId}', + ['x_auth_token', 'tenantId', + 'description'], + 'tenant', + x_auth_token='header', + description='req') + delete_tenant = simplerest.RESTMethod('delete_tenant', 'DELETE', + '/tenants/{tenantId}', + ['x_auth_token', 'tenantId'], + x_auth_token='header') + + get_base_urls = simplerest.RESTMethod('get_base_urls', 'GET', + '/baseURLs', + ['x_auth_token', 'serviceName'], + x_auth_token='header', + serviceName='query') + get_enabled_base_urls = simplerest.RESTMethod('get_enabled_base_urls', + 'GET', '/baseURLs/enabled', + ['x_auth_token', + 'serviceName'], + x_auth_token='header', + serviceName='query') + get_base_url = simplerest.RESTMethod('get_base_url', 'GET', + '/baseURLs/{baseURLId}', + ['x_auth_token', 'baseURLId'], + x_auth_token='header') + get_base_url_refs = simplerest.RESTMethod('get_base_url_refs', 'GET', + '/tenants/{tenantId}/' + 'baseURLRefs', + ['x_auth_token', 'tenantId'], + x_auth_token='header') + add_base_url_ref = simplerest.RESTMethod('add_base_url_ref', 'POST', + '/tenants/{tenantId}/' + 'baseURLRefs', + ['x_auth_token', + 'tenantId', 'id', 'region', + 'default', 'serviceName', + 'publicURL', 'internalURL', + 'enabled'], 'baseURL', + x_auth_token='header', + id='req', region='req', + default='req', + serviceName='req', + publicURL='req', + internalURL='req', enabled='req') + get_base_url_ref = simplerest.RESTMethod('get_base_url_ref', 'GET', + '/tenants/{tenantId}/' + 'baseURLRefs/{baseURLId}', + ['x_auth_token', 'tenantId', + 'baseURLId'], + x_auth_token='header') + delete_base_url_ref = simplerest.RESTMethod('delete_base_url_ref', + 'DELETE', + '/tenants/{tenantId}/' + 'baseURLRefs/{baseURLId}', + ['x_auth_token', 'tenantId', + 'baseURLId'], + x_auth_token='header') + + get_roles = simplerest.RESTMethod('get_roles', 'GET', '/roles', + ['x_auth_token', 'serviceName'], + x_auth_token='header', + serviceName='query') + get_role = simplerest.RESTMethod('get_role', 'GET', '/roles/{roleId}', + ['x_auth_token', 'roleId'], + x_auth_token='header') + get_role_refs = simplerest.RESTMethod('get_role_refs', 'GET', + '/users/{userId}/roleRefs', + ['x_auth_token', 'userId'], + x_auth_token='header') + add_role_ref = simplerest.RESTMethod('add_role_ref', 'POST', + '/users/{userId}/roleRefs', + ['x_auth_token', 'userId', 'id', + 'href', 'tenantId'], + 'roleRef', x_auth_token='header', + id='req', href='req', tenantId='req') + get_role_ref = simplerest.RESTMethod('get_role_ref', 'GET', + '/users/{userId}/roleRefs/{roleId}', + ['x_auth_token', 'userId', 'roleId'], + x_auth_token='header') + delete_role_ref = simplerest.RESTMethod('delete_role_ref', 'DELETE', + '/users/{userId}/roleRefs/' + '{roleId}', + ['x_auth_token', 'userId', + 'roleId'], + x_auth_token='header') diff --git a/keystone/test/functional/run_tests.py b/keystone/test/functional/run_tests.py new file mode 100755 index 00000000..2d699683 --- /dev/null +++ b/keystone/test/functional/run_tests.py @@ -0,0 +1,61 @@ +#!/usr/bin/python +# vim: tabstop=4 shiftwidth=4 softtabstop=4 +# Copyright (c) 2011 OpenStack, LLC. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import base +try: + import dtest +except: + print "DTest framework needed. Try running 'pip install dtest'" + exit() +import sys + + +def add_opts(opts): + """Adds options specific to this test suite.""" + + opts.add_option("-u", "--username", + action="store", type="string", dest="username", + help="The username to use to access Keystone.") + opts.add_option("-p", "--password", + action="store", type="string", dest="password", + help="The password to use to access Keystone.") + opts.add_option("-k", "--keystone", + action="store", type="string", dest="keystone", + help="The URL to use to access Keystone.") + + return opts + + +if __name__ == '__main__': + # Obtain the options + opts = add_opts(dtest.optparser(usage="%prog [options]")) + + # Process command-line arguments, saving them so tests can get to + # them + (base.options, args) = opts.parse_args() + + # Ensure required options are present + if (not base.options.username or not base.options.password or + not base.options.keystone): + print >>sys.stderr, "Missing required options" + print >>sys.stderr, ("At a minimum, --username, --password, and " + "--keystone must be specified.") + opts.print_help(sys.stderr) + sys.exit(1) + + # Execute the test suite + sys.exit(dtest.main(**dtest.opts_to_args(base.options))) diff --git a/keystone/test/functional/sample_test.py b/keystone/test/functional/sample_test.py new file mode 100644 index 00000000..10d24abe --- /dev/null +++ b/keystone/test/functional/sample_test.py @@ -0,0 +1,85 @@ +## Lines beginning with '##' are for explaining the contents of this +## file, and should be removed if you copy the file to create a new +## (set of) tests. Also note that the file must be named to match the +## scheme "test_[...].py", i.e., "test_tokens.py". +## +## I don't think I need to explain the copyright notice :) +## +# vim: tabstop=4 shiftwidth=4 softtabstop=4 +# Copyright (c) 2011 OpenStack, LLC. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +## This test suite uses the DTest framework, which can be found on +## PyPi ("pip install dtest"). DTest uses threading to perform tests +## in parallel; the threading can be limited by using dependencies, +## but the purpose of dependencies is really to say that some test +## must pass before other actions can be performed. Within dtest, the +## util module contains a number of useful "assert_*()" functions, but +## if you want, you can just use the "assert" statement. +## +## Also note that names are important. Modules should be named +## "test_[...].py", as mentioned above. Classes must extend +## base.KeystoneTest (a subclass of dtest.DTestCase), and test methods +## should have names like "test_[...]" (or be decorated with the +## @dtest.istest decorator). Adhere to these rules, and DTest can +## discover and run the tests without you having to do anything other +## than create them. +import dtest +from dtest import util + +## The "base" module contains KeystoneTest, which ensures that there's +## a Keystone authentication token in self.token and an API accessor +## in self.ks. See ksapi.py for a list of what methods are available +## on self.ks. +import base + + +## Tests should be gathered together in classes, not too dissimilar +## from how unittest works. Extend base.KeystoneTest, so you get +## self.token and self.ks. If you override setUp(), make sure you +## call the superclass's setUp() method (it's responsible for setting +## self.ks). Try to avoid overriding setUpClass() or tearDownClass() +## if you can help it (they're responsible for setting up and +## destroying self.token). +class SampleTest(base.KeystoneTest): + def test_sample(self): + """Test that we can do sample.""" + ## You don't *have* to declare a doc string, but it's good + ## practice. + + ## Here we're making a "sample_call()", passing self.token as + ## the authentication token. For available calls and the + ## order of arguments, check out ksapi.py. The return value + ## will be an httplib.HTTPResponse object with additional + ## 'body' (str) and 'obj' (dict) attributes. If a status code + ## greater than or equal to 400 is returned from the other + ## end, an exception will be raised; the response will be + ## attached to the 'response' attribute of the exception, and + ## the status will be on the 'status' attribute of the + ## exception. Note that redirects are followed. + resp = self.ks.sample_call(self.token, 'argument 1', 'argument 2') + + # Verify that resp is correct + util.assert_equal(resp.status, 200) + util.assert_in('sample', resp.obj) + ## Place your various assertions about the response here. + + ## Rinse, lather, repeat. You should perform only a single + ## test per test method, but if you're doing creation tests, + ## it makes sense to include the deletion test in the same + ## test method. Remember, the only control you have over test + ## ordering is by setting up dependencies (@dtest.depends()). + ## No return value is necessary. diff --git a/keystone/test/functional/simplerest.py b/keystone/test/functional/simplerest.py new file mode 100644 index 00000000..8455ece3 --- /dev/null +++ b/keystone/test/functional/simplerest.py @@ -0,0 +1,641 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 +# Copyright (c) 2011 OpenStack, LLC. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +import httplib +import json +import re +import string +import urllib +import urlparse + + +class HTTPRequest(object): + """Represent an HTTP request. + + Represents an HTTP request. Headers can be manipulated using + standard dictionary access (i.e., req["accept"] will be the + contents of the "Accept" header), and the body can be fed in using + write(). Note that headers are manipulated in a case-insensitive + fashion; that is, the "accept" header is the same thing as the + "ACCEPT" header or the "aCcEpT" header. + + """ + + def __init__(self, method, uri, body=None, headers=None): + """Initialize an HTTP request. + + :param method: The HTTP method, i.e., "GET". + :param uri: The full path of the resource. + :param body: A string giving the body of the request. + :param headers: A dictionary of headers. + """ + + # Save the relevant data + self.method = method.upper() + self.uri = uri + self.body = body or '' + self.headers = {} + + # Set the headers... + if headers: + for hdr, value in headers.items(): + # Allows appropriate case mapping + self[hdr] = value + + def write(self, data): + """Write data to the request body. + + :param data: Data to be appended to the request body. + """ + + # Add the written data to our body + self.body += data + + def flush(self): + """Flush data to the request body. + + Does nothing. Provided just in case something tries to call + flush(). + """ + + # Do-nothing to allow stream compatibility + pass + + def __getitem__(self, item): + """Allow access to headers.""" + + # Headers are done by item access + return self.headers[item.title()] + + def __setitem__(self, item, value): + """Allow access to headers.""" + + # Headers are done by item access + self.headers[item.title()] = value + + def __delitem__(self, item): + """Allow access to headers.""" + + # Headers are done by item access + del self.headers[item.title()] + + def __contains__(self, item): + """Allow access to headers.""" + + # Headers are done by item access + return item.title() in self.headers + + def __len__(self): + """Allow access to headers.""" + + # Headers are done by item access + return len(self.headers) + + +class RESTClient(object): + """Represent a REST client connection. + + Represents a REST client connection. All calls will be made + relative to the base URL defined when the class is instantiated. + Note that 301, 302, 303, and 307 redirects are honored. By + default, redirects are limited to a maximum of 10; this may be + modified by setting the max_redirects class attribute. + + """ + + # Maximum number of redirects we'll follow + max_redirects = 10 + + def __init__(self, baseurl, debug_stream=None): + """Initialize a REST client. + + :param baseurl: The base URL for the client connection. + :param debug_stream: An optional stream for receiving debug. + """ + + # Save the base URL and debug stream + self._baseurl = baseurl + self._debug_stream = debug_stream + + # Pull it apart, also... + parsed = urlparse.urlparse(baseurl) + + # Make sure the scheme makes sense + if parsed.scheme not in ('http', 'https'): + raise httplib.InvalidURL("invalid scheme: '%s'" % parsed.scheme) + + # We're only concerned with the scheme, netloc, and path... + self._scheme = parsed.scheme + self._netloc = parsed.netloc + self._path = parsed.path or '/' + + # We'll keep a cached HTTPConnection for our baseurl around... + self._connect = None + + @classmethod + def _open(cls, scheme, netloc, cache=None): + """Open an HTTPConnection. + + Opens an HTTPConnection or returns an open one from the cache, + if given. If the scheme is "https", returns an + HTTPSConnection. + + :param scheme: The URI scheme; one of 'http' or 'https'. + :param netloc: The network location. + :param cache: Optional dictionary caching connections. + """ + + # If cache is present, look up the scheme and netloc in it... + if cache and (scheme, netloc) in cache: + # Return the pre-existing connection + return cache[(scheme, netloc)] + + # Open a connection for the given scheme and netloc + if scheme == 'http': + connect = httplib.HTTPConnection(netloc) + elif scheme == 'https': + connect = httplib.HTTPSConnection(netloc) + + # Make sure to cache it... + if cache is not None: + cache[(scheme, netloc)] = connect + + return connect + + def _debug(self, msg, *args, **kwargs): + """Generate debugging output.""" + + # If we have a declared debug stream, output to it + if self._debug_stream: + print >>self._debug_stream, msg % (kwargs if kwargs else args) + + def make_req(self, method, reluri, query=None, obj=None, headers=None): + """Makes an HTTPRequest. + + Generates an instance of HTTPRequest and returns it. + + :param method: The HTTP method, i.e., "GET". + :param reluri: The resource URI, relative to the base URL. + :param query: Optional dictionary to convert into a query. + :param obj: Optional object to serialize as a JSON object. + :param headers: Optional dictionary of headers. + """ + + # First, let's compose the path with the reluri + joincond = (self._path[-1:], reluri[:1]) + if joincond == ('/', '/'): + fulluri = self._path + reluri[1:] + elif '/' in joincond: + fulluri = self._path + reluri + else: + fulluri = self._path + '/' + reluri + + # Add the query, if there is one + if query: + fulluri += '?%s' % urllib.urlencode(query) + + self._debug("Creating %s request for %s", method, fulluri) + + # Set up a default for the accept header + if headers is None: + headers = {} + headers.setdefault('accept', 'application/json') + + # Build a request + req = HTTPRequest(method, fulluri, headers=headers) + + # If there's an object, jsonify it + if obj is not None: + json.dump(obj, req) + req['content-type'] = 'application/json' + self._debug(" Request body: %r" % req.body) + + # Now, return the request + return req + + def send(self, req): + """Send request. + + Sends a request, which must have been generated using + make_req() (assumes URL is relative to the base URL). Honors + redirects (even to URLs not relative to base URL). If the + status code of the response is >= 400, raises an appropriate + exception derived from HTTPException (of this module). + Returns an HTTPResponse (defined by httplib). If a JSON + object is available in the body, the obj attribute of the + response will be set to it; otherwise, obj is None. + """ + + self._debug("Sending request on client %s: (%r, %r, %r, %r)", + self._baseurl, req.method, req.uri, req.body, req.headers) + + # First, get a connection + if self._connect is None: + self._connect = self._open(self._scheme, self._netloc) + + # Pre-initialize the cache... + cache = {(self._scheme, self._netloc): self._connect} + + # Get the initial connection we'll be using... + connect = self._connect + + # Also get the initial URI we're using... + uri = req.uri + + # Need the full URL, with e.g., netloc + fullurl = urlparse.urlunparse((self._scheme, self._netloc, uri, + None, None, None)) + + # Loop for redirection handling + seen = set([fullurl]) + for i in range(self.max_redirects): + # Make the request + self._debug(" Issuing request to %s (%s)", fullurl, uri) + connect.request(req.method, uri, req.body, req.headers) + + # Get the response + resp = connect.getresponse() + + # Now, is the response a redirection? + newurl = None + if resp.status in (301, 302, 303, 307): + # Find the forwarding header... + if 'location' in resp.msg: + newurl = resp.getheader('location') + elif 'uri' in resp.msg: + newurl = resp.getheader('uri') + + # If we have a newurl, process the redirection + if newurl is not None: + # Canonicalize it; it could be relative + fullurl = urlparse.urljoin(fullurl, newurl) + + self._debug(" Got redirected to %s" % fullurl) + + # Make sure we haven't seen it before... + if fullurl in seen: + self._debug(" Redirected URL already seen!") + break + + seen.add(fullurl) + + # Now, split it back up + tmp = urlparse.urlparse(newurl) + + # Get the path part of the URL + uri = urlparse.urlunparse((None, None, tmp.path, tmp.params, + tmp.query, tmp.fragment)) + + # Finally, get a connection + connect = self._open(tmp.scheme, tmp.netloc, cache) + + # And we try again + continue + + # We have a response and it's not a redirection; let's + # interpret the JSON in the response (safely)... + self._debug(" Received %s response (%s)", resp.status, + resp.reason) + resp.body = resp.read() + try: + resp.obj = json.loads(resp.body) + self._debug(" Received entity: %r", resp.obj) + except ValueError: + resp.obj = None + self._debug(" No received entity; body %r", resp.body) + + # If this is an error response, let's raise an appropriate + # exception + if resp.status >= 400: + exc = exceptions.get(resp.status, HTTPException) + self._debug(" Response was a fault, raising %s", + exc.__name__) + raise exc(resp) + + # Return the response + return resp + + # Exceeded the maximum number of redirects + self._debug(" Redirect loop detected") + raise RESTException("Redirect loop detected") + + def get(self, reluri, query=None, headers=None): + """Send a GET request. + + :param reluri: The resource URI, relative to the base URL. + :param query: Optional dictionary to convert into a query. + :param headers: Optional dictionary of headers. + """ + + # Make a GET request... + req = self.make_req('GET', reluri, query=query, headers=headers) + + # And issue it + return self.send(req) + + def put(self, reluri, query=None, obj=None, headers=None): + """Send a PUT request. + + :param reluri: The resource URI, relative to the base URL. + :param query: Optional dictionary to convert into a query. + :param obj: Optional object to serialize as a JSON object. + :param headers: Optional dictionary of headers. + """ + + # Make a PUT request... + req = self.make_req('PUT', reluri, query=query, obj=obj, + headers=headers) + + # And issue it + return self.send(req) + + def post(self, reluri, query=None, obj=None, headers=None): + """Send a POST request. + + :param reluri: The resource URI, relative to the base URL. + :param query: Optional dictionary to convert into a query. + :param obj: Optional object to serialize as a JSON object. + :param headers: Optional dictionary of headers. + """ + + # Make a POST request... + req = self.make_req('POST', reluri, query=query, obj=obj, + headers=headers) + + # And issue it + return self.send(req) + + def delete(self, reluri, query=None, headers=None): + """Send a DELETE request. + + :param reluri: The resource URI, relative to the base URL. + :param query: Optional dictionary to convert into a query. + :param headers: Optional dictionary of headers. + """ + + # Make a DELETE request... + req = self.make_req('DELETE', reluri, query=query, headers=headers) + + # And issue it + return self.send(req) + + +class RESTException(Exception): + """Superclass for exceptions from this module.""" + + pass + + +class HTTPException(RESTException): + """Superclass of exceptions raised if an error status is returned.""" + + def __init__(self, response): + """Initializes exception, attaching response.""" + + # Formulate a message from the response + msg = response.reason + + # Initialize superclass + super(RESTException, self).__init__(msg) + + # Also attach status code and the response + self.status = response.status + self.response = response + + +# Set up more specific exceptions +exceptions = {} +for _status, _name in httplib.responses.items(): + # Skip non-error codes + if _status < 400: + continue + + # Make a valid name + _exname = re.sub(r'\W+', '', _name) + 'Exception' + + # Make a class + _cls = type(_exname, (HTTPException,), {'__doc__': _name}) + + # Now, put it in the right places + vars()[_name] = _cls + exceptions[_status] = _cls + + +class RESTMethod(object): + """Represent a REST method. + + Represents a class method which should be translated into a + request to a REST server. + + """ + + def __init__(self, name, method, uri, argorder=None, reqwrapper=None, + **kwargs): + """Initialize a REST method. + + Creates a method that will use the defined HTTP method to + access the defined resource. Extra keyword arguments specify + the names and dispositions of arguments not derived from the + uri format string. The values of those extra arguments may be + 'query', 'req', or 'header', to indicate that the argument + goes in the query string, the request object, or the request + headers. (Note that header names have '_' mapped to '-' for + convenience.) If a value is a tuple, the first element of the + tuple must be the type ('query', 'req', or 'header'), and the + second element must be either True or False, to indicate that + the argument is required. By default, all query arguments are + optional, and all other arguments are required. + + :param name: The method name. + :param method: The corresponding HTTP method. + :param uri: A relative URI for the resource. A format string. + :param reqwrapper: Key for the wrapping dictionary of the request. + :param argorder: Order arguments may be specified in. + """ + + # Save our name and method + self.name = name + self.method = method.upper() + + # Need to save the various construction information + self.uri = uri + self.reqwrapper = reqwrapper + self.argorder = argorder or [] + + # Need to determine what keys are required and where they + # go... + self.kwargs = {} + + # Start by parsing the uri format string + for text, field, fmt, conv in string.Formatter().parse(uri): + # Add field as a required kw argument + if field is not None: + self.kwargs[field] = ('uri', True) + + # Now consider other mentioned arguments... + for field, type_ in kwargs.items(): + # Don't allow duplicate fields + if field in self.kwargs: + raise RESTException("Field %r of %s() already defined as %r" % + (field, name, self.kwargs[field][0])) + + # If type_ is a tuple, first element is type and second is + # required or not + required = None + if isinstance(type_, (tuple, list)): + required = type_[1] + type_ = type_[0] + + # Ensure valid type... + if (type_ not in ('query', 'req', 'header') or + (type_ == 'req' and reqwrapper is None)): + raise RESTException("Invalid type %r for field %r of %s()" % + (type_, field, name)) + + # For query arguments, required defaults to False + if required is None: + if type_ == 'query': + required = False + else: + required = True + + # Add the field + self.kwargs[field] = (type_, required) + + def __get__(self, obj, owner): + """Retrieve a wrapper to call this REST method.""" + + # If access via class, return ourself + if obj is None: + return self + + # OK, construct a wrapper to call the method with the + # appropriate RESTClient + def wrapper(*args, **kwargs): + # Build a dictionary from zipping together argorder and + # args + newkw = dict(zip(self.argorder, args)) + + # Make kwargs override + newkw.update(kwargs) + + return self(obj._rc, newkw) + + # Copy over the name for prettiness sake + wrapper.__name__ = self.name + wrapper.func_name = self.name + + return wrapper + + def __call__(self, rc, kwargs): + """Call this REST method. + + :param rc: A RESTClient instance. + :param kwargs: A dictionary of arguments to this REST method. + """ + + rc._debug("Called %s(%r)", self.name, kwargs) + + # We're going to build an object, a query, and headers + headers = {} + query = {} + if self.reqwrapper is None: + obj = None + reqobj = None + else: + obj = {} + reqobj = {self.reqwrapper: obj} + + # Let's walk through kwargs and make sure our required + # arguments are present + seen = set() + for field, (type_, required) in self.kwargs.items(): + # Is the field present? + if field not in kwargs: + # Is it required? + if required: + rc._debug(" Required %r argument %r missing", + type_, field) + raise RESTException("Missing required argument " + "%r of %s()" % + (field, self.name)) + + # Not required, don't worry about it + rc._debug(" Optional %r argument %r missing", + type_, field) + continue + + # Send it to the right place + if type_ == 'query': + rc._debug(" Query argument %r: %r", field, kwargs[field]) + query[field] = kwargs[field] + elif type_ == 'req': + rc._debug(" Request object argument %r: %r", field, + kwargs[field]) + obj[field] = kwargs[field] + elif type_ == 'header': + # Reformulate the name + hdr = '-'.join(field.split('_')).title() + rc._debug(" Header %r argument %r: %r", hdr, field, + kwargs[field]) + headers[hdr] = kwargs[field] + + # Keep track of arguments we've used + seen.add(field) + + # Deal with unprocessed arguments + if obj is not None: + for arg in set(kwargs.keys()) - seen: + rc._debug(" Extra request object argument %r: %r", + arg, kwargs[arg]) + obj[arg] = kwargs[arg] + + # Format the URI + uri = self.uri.format(**kwargs) + rc._debug(" Request URI: %s", uri) + + # We now have all the pieces we need; create a request... + req = rc.make_req(self.method, uri, query, reqobj, headers) + + # And send it + return rc.send(req) + + +class RESTAPI(object): + """Represent a REST API. + + A convenient superclass for defining REST APIs using this toolkit. + Methods should be defined by assigning instances of RESTMethod to + class variables. + + """ + + def __init__(self, baseurl, debug_stream=None): + """Initialize a REST API. + + Creates a RESTClient instance from the baseurl and attaches it + where RESTMethod expects to find it. + """ + + # Create and save a RESTClient for our use + self._rc = RESTClient(baseurl, debug_stream) + + @property + def rc(self): + """Retrieve the RESTClient instance.""" + + return self._rc diff --git a/keystone/test/functional/test_tokens.py b/keystone/test/functional/test_tokens.py new file mode 100644 index 00000000..0575e22e --- /dev/null +++ b/keystone/test/functional/test_tokens.py @@ -0,0 +1,51 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 +# Copyright (c) 2011 OpenStack, LLC. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +import dtest +from dtest import util + +import base + + +class AuthenticateTest(base.BaseKeystoneTest): + def test_authenticate(self): + """Test that we can authenticate using Keystone.""" + + # Issue the authentication request + resp = self.ks.authenticate(base.options.username, + base.options.password) + + # Verify that resp is correct + util.assert_equal(resp.status, 200) + util.assert_in('auth', resp.obj) + util.assert_in('token', resp.obj['auth']) + util.assert_in('expires', resp.obj['auth']['token']) + util.assert_in('id', resp.obj['auth']['token']) + # util.assert_in('user', resp.obj['auth']) + # util.assert_in('username', resp.obj['auth']['user']) + # util.assert_in('tenantId', resp.obj['auth']['user']) + # util.assert_equal(resp.obj['auth']['user']['username'], + # base.options.username) + + # Now ensure we can revoke an authentication token + auth_tok = resp.obj['auth']['token']['id'] + resp = self.ks.revoke_token(auth_tok, auth_tok) + util.assert_equal(resp.status, 204) + + +# Ensure that all remaining tests wait for test_authenticate +dtest.depends(AuthenticateTest.test_authenticate)(base.KeystoneTest.setUpClass) diff --git a/keystone/test/unit/__init__.py b/keystone/test/unit/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/keystone/test/unit/base.py b/keystone/test/unit/base.py new file mode 100644 index 00000000..0d59bba1 --- /dev/null +++ b/keystone/test/unit/base.py @@ -0,0 +1,282 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 +# Copyright (c) 2011 OpenStack, LLC. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Base test case classes for the unit tests""" + +import datetime +import functools +import json +import httplib +import logging +import pprint +import unittest + +from lxml import etree, objectify +import webob + +from keystone import server +from keystone.db.sqlalchemy import api as db_api + +logger = logging.getLogger('test.unit.base') + + +class ServiceAPITest(unittest.TestCase): + + """ + Base test case class for any unit test that tests the main service API. + """ + + """ + The `api` attribute for this base class is the `server.KeystoneAPI` + controller. + """ + api_class = server.KeystoneAPI + + """ + Dict of configuration options to pass to the API controller + """ + options = {'sql_connection': 'sqlite:///', # in-memory db + 'verbose': False, + 'debug': False} + + """ + Set of dicts of tenant attributes we start each test case with + """ + tenant_fixtures = [ + {'id': 'tenant1', + 'enabled': True, + 'desc': 'tenant1'} + ] + + """ + Attributes of the user the test creates for each test case that + will authenticate against the API. The `auth_user` attribute + will contain the created user with the following attributes. + """ + auth_user_attrs = {'id': 'auth_user', + 'password': 'auth_pass', + 'email': 'auth_user@example.com', + 'enabled': True, + 'tenant_id': 'tenant1'} + """ + Special attribute that is the identifier of the token we use in + authenticating. Makes it easy to test the authentication process. + """ + auth_token_id = 'SPECIALAUTHTOKEN' + + """ + Content-type of requests. Generally, you don't need to manually + change this. Instead, :see test.unit.decorators + """ + content_type = 'json' + + """ + Version of the API to test + """ + api_version = '2.0' + + def setUp(self): + self.api = self.api_class(self.options) + + self.expires = datetime.datetime.utcnow() + self.clear_all_data() + + # Create all our base tenants + for tenant in self.tenant_fixtures: + self.fixture_create_tenant(**tenant) + + # Create the user we will authenticate with + self.auth_user = self.fixture_create_user(**self.auth_user_attrs) + self.auth_token = self.fixture_create_token( + user_id=self.auth_user['id'], + tenant_id=self.auth_user['tenant_id'], + expires=self.expires, + token_id=self.auth_token_id) + + self.add_verify_status_helpers() + + def tearDown(self): + self.clear_all_data() + setattr(self, 'req', None) + setattr(self, 'res', None) + + def clear_all_data(self): + """ + Purges the database of all data + """ + db_api.unregister_models() + logger.debug("Cleared all data from database") + db_api.register_models() + + def fixture_create_tenant(self, **kwargs): + """ + Creates a tenant fixture. + + :params **kwargs: Attributes of the tenant to create + """ + values = kwargs.copy() + tenant = db_api.tenant_create(values) + logger.debug("Created tenant fixture %s", values['id']) + return tenant + + def fixture_create_user(self, **kwargs): + """ + Creates a user fixture. If the user's tenant ID is set, and the tenant + does not exist in the database, the tenant is created. + + :params **kwargs: Attributes of the user to create + """ + values = kwargs.copy() + tenant_id = values.get('tenant_id') + if tenant_id: + if not db_api.tenant_get(tenant_id): + db_api.tenant_create({'id': tenant_id, + 'enabled': True, + 'desc': tenant_id}) + user = db_api.user_create(values) + logger.debug("Created user fixture %s", values['id']) + return user + + def fixture_create_token(self, **kwargs): + """ + Creates a token fixture. + + :params **kwargs: Attributes of the token to create + """ + values = kwargs.copy() + token = db_api.token_create(values) + logger.debug("Created token fixture %s", values['token_id']) + return token + + def get_request(self, method, url, headers=None): + """ + Sets the `req` attribute to a `webob.Request` object that + is constructed with the supplied method and url. Supplied + headers are added to appropriate Content-type headers. + """ + headers = headers or {} + self.req = webob.Request.blank('/v%s/%s' % (self.api_version, + url.lstrip('/'))) + self.req.method = method + self.req.headers = headers + if 'content-type' not in headers: + ct = 'application/%s' % self.content_type + self.req.headers['content-type'] = ct + self.req.headers['accept'] = ct + return self.req + + def get_response(self): + """ + Sets the appropriate headers for the `req` attribute for + the current content type, then calls `req.get_response()` and + sets the `res` attribute to the returned `webob.Response` object + """ + self.res = self.req.get_response(self.api) + logger.debug("%s %s returned %s", self.req.method, self.req.path_qs, + self.res.status) + if self.res.status_int != httplib.OK: + logger.debug("Response Body:") + for line in self.res.body.split("\n"): + logger.debug(line) + return self.res + + def verify_status(self, status_code): + """ + Simple convenience wrapper for validating a response's status + code. + """ + if not getattr(self, 'res'): + raise RuntimeError("Called verify_status() before calling " + "get_response()!") + + self.assertEqual(status_code, self.res.status_int, + "Incorrect status code %d. Expected %d" % + (self.res.status_int, status_code)) + + def add_verify_status_helpers(self): + """ + Adds some convenience helpers using partials... + """ + self.status_ok = functools.partial(self.verify_status, + httplib.OK) + self.status_not_found = functools.partial(self.verify_status, + httplib.NOT_FOUND) + self.status_unauthorized = functools.partial(self.verify_status, + httplib.UNAUTHORIZED) + self.status_bad_request = functools.partial(self.verify_status, + httplib.BAD_REQUEST) + + def assert_dict_equal(self, expected, got): + """ + Compares two dicts for equality and prints the dictionaries + nicely formatted for easy comparison if there is a failure. + """ + self.assertEqual(expected, got, "Mappings are not equal.\n" + "Got:\n%s\nExpected:\n%s" % + (pprint.pformat(got), + pprint.pformat(expected))) + + def assert_xml_strings_equal(self, expected, got): + """ + Compares two XML strings for equality by parsing them both + into DOMs. Prints the DOMs nicely formatted for easy comparison + if there is a failure. + """ + # This is a nice little trick... objectify.fromstring() returns + # a DOM different from etree.fromstring(). The objectify version + # removes any different whitespacing... + got = objectify.fromstring(got) + expected = objectify.fromstring(expected) + self.assertEqual(etree.tostring(expected), + etree.tostring(got), "DOMs are not equal.\n" + "Got:\n%s\nExpected:\n%s" % + (etree.tostring(got, pretty_print=True), + etree.tostring(expected, pretty_print=True))) + + +class AdminAPITest(ServiceAPITest): + + """ + Base test case class for any unit test that tests the admin API. The + """ + + """ + The `api` attribute for this base class is the `server.KeystoneAdminAPI` + controller. + """ + api_class = server.KeystoneAdminAPI + + """ + Set of dicts of tenant attributes we start each test case with + """ + tenant_fixtures = [ + {'id': 'tenant1', + 'enabled': True, + 'desc': 'tenant1'}, + {'id': 'tenant2', + 'enabled': True, + 'desc': 'tenant2'} + ] + + """ + Attributes of the user the test creates for each test case that + will authenticate against the API. + """ + auth_user_attrs = {'id': 'admin_user', + 'password': 'admin_pass', + 'email': 'admin_user@example.com', + 'enabled': True, + 'tenant_id': 'tenant2'} diff --git a/keystone/test/unit/decorators.py b/keystone/test/unit/decorators.py new file mode 100644 index 00000000..17a7d432 --- /dev/null +++ b/keystone/test/unit/decorators.py @@ -0,0 +1,49 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 +# Copyright (c) 2011 OpenStack, LLC. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +"""Decorators useful in unit tests""" + +import functools + + +def content_type(func, content_type='json'): + """ + Decorator for a test case method that sets the test case's + content_type to 'json' or 'xml' and resets it afterwards to + the original setting. This also asserts that if there is a + value for the test object's `res` attribute, that the content-type + header of the response is correct. + """ + @functools.wraps(func) + def wrapped(*a, **kwargs): + test_obj = a[0] + orig_content_type = test_obj.content_type + try: + test_obj.content_type = content_type + func(*a, **kwargs) + if getattr(test_obj, 'res'): + expected = 'application/%s' % content_type + got = test_obj.res.headers['content-type'].split(';')[0] + test_obj.assertEqual(expected, got, + "Bad content type: %s. Expected: %s" % + (got, expected)) + finally: + test_obj.content_type = orig_content_type + return wrapped + + +jsonify = functools.partial(content_type, content_type='json') +xmlify = functools.partial(content_type, content_type='xml') diff --git a/keystone/test/unit/test_BaseURLs.py b/keystone/test/unit/test_BaseURLs.py new file mode 100644 index 00000000..fa352f93 --- /dev/null +++ b/keystone/test/unit/test_BaseURLs.py @@ -0,0 +1,667 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 +# Copyright (c) 2010-2011 OpenStack, LLC. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +import httplib2 +import json +from lxml import etree +import os +import sys +sys.path.append(os.path.abspath(os.path.join(os.path.abspath(__file__), + '..', '..', '..', '..', 'keystone'))) +import unittest + +import test_common as utils +from test_common import URL + +class BaseURLsTest(unittest.TestCase): + def setUp(self): + self.tenant = utils.get_tenant() + self.password = utils.get_password() + self.email = utils.get_email() + self.user = utils.get_user() + self.userdisabled = utils.get_userdisabled() + self.auth_token = utils.get_auth_token() + self.exp_auth_token = utils.get_exp_auth_token() + self.disabled_token = utils.get_disabled_token() + self.missing_token = utils.get_none_token() + self.invalid_token = utils.get_non_existing_token() + utils.create_tenant(self.tenant, str(self.auth_token)) + utils.create_user(self.tenant, self.user, self.auth_token) + self.token = utils.get_token(self.user, 'secrete', self.tenant, + 'token') + + def tearDown(self): + utils.delete_user(self.tenant, self.user, self.auth_token) + utils.delete_tenant(self.tenant, self.auth_token) + utils.delete_all_baseurls_ref(self.tenant, self.auth_token) + +class GetBaseURLsTest(BaseURLsTest): + def test_get_baseURLs(self): + header = httplib2.Http(".cache") + url = '%sbaseURLs' % (utils.URL) + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body='{}', + headers={"Content-Type": "application/json", + "X-Auth-Token": self.auth_token}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(200, int(resp['status'])) + + #verify content + obj = json.loads(content) + if not "baseURLs" in obj: + raise self.fail("Expecting BaseURLs") + + def test_get_baseURLs_using_expired_auth_token(self): + header = httplib2.Http(".cache") + url = '%sbaseURLs' % (utils.URL) + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body='{}', + headers={"Content-Type": "application/json", + "X-Auth-Token": self.exp_auth_token}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(403 , int(resp['status'])) + + def test_get_baseURLs_using_disabled_auth_token(self): + header = httplib2.Http(".cache") + url = '%sbaseURLs' % (utils.URL) + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body='{}', + headers={"Content-Type": "application/json", + "X-Auth-Token": self.disabled_token}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(403 , int(resp['status'])) + + def test_get_baseURLs_using_missing_auth_token(self): + header = httplib2.Http(".cache") + url = '%sbaseURLs' % (utils.URL) + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body='{}', + headers={"Content-Type": "application/json", + "X-Auth-Token": self.missing_token}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(401 , int(resp['status'])) + + def test_get_baseURLs_using_invalid_auth_token(self): + header = httplib2.Http(".cache") + url = '%sbaseURLs' % (utils.URL) + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body='{}', + headers={"Content-Type": "application/json", + "X-Auth-Token": self.invalid_token}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(404 , int(resp['status'])) + + def test_get_baseURLs_xml(self): + header = httplib2.Http(".cache") + url = '%sbaseURLs' % (utils.URL) + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body='{}', + headers={"Content-Type": "application/xml", + "X-Auth-Token": self.auth_token, + "ACCEPT": "application/xml"}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(200, int(resp['status'])) + + #verify content + dom = etree.Element("root") + dom.append(etree.fromstring(content)) + baseURLs = dom.find("{http://docs.openstack.org/identity/api/v2.0}" \ + "baseURLs") + if baseURLs == None: + self.fail("Expecting BaseURLs") + + def test_get_baseURLs_xml_expired_auth_token(self): + header = httplib2.Http(".cache") + url = '%sbaseURLs' % (utils.URL) + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body='{}', + headers={"Content-Type": "application/xml", + "X-Auth-Token": self.exp_auth_token, + "ACCEPT": "application/xml"}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(403, int(resp['status'])) + + def test_get_baseURLs_xml_disabled_auth_token(self): + header = httplib2.Http(".cache") + url = '%sbaseURLs' % (utils.URL) + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body='{}', + headers={"Content-Type": "application/xml", + "X-Auth-Token": self.disabled_token, + "ACCEPT": "application/xml"}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(403, int(resp['status'])) + + def test_get_baseURLs_xml_missing_auth_token(self): + header = httplib2.Http(".cache") + url = '%sbaseURLs' % (utils.URL) + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body='{}', + headers={"Content-Type": "application/xml", + "X-Auth-Token": self.missing_token, + "ACCEPT": "application/xml"}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(401, int(resp['status'])) + + def test_get_baseURLs_xml_invalid_auth_token(self): + header = httplib2.Http(".cache") + url = '%sbaseURLs' % (utils.URL) + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body='{}', + headers={"Content-Type": "application/xml", + "X-Auth-Token": self.invalid_token, + "ACCEPT": "application/xml"}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(404, int(resp['status'])) + +class GetBaseURLTest(BaseURLsTest): + def test_get_baseURL(self): + header = httplib2.Http(".cache") + url = '%sbaseURLs/%s' % (utils.URL, '1') + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body='{}', + headers={"Content-Type": "application/json", + "X-Auth-Token": self.auth_token}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(200, int(resp['status'])) + + #verify content + obj = json.loads(content) + if not "baseURL" in obj: + raise self.fail("Expecting BaseURL") + + def test_get_baseURL_using_expired_auth_token(self): + header = httplib2.Http(".cache") + url = '%sbaseURLs/%s' % (utils.URL, '1') + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body='{}', + headers={"Content-Type": "application/json", + "X-Auth-Token": self.exp_auth_token}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(403, int(resp['status'])) + + def test_get_baseURL_using_disabled_auth_token(self): + header = httplib2.Http(".cache") + url = '%sbaseURLs/%s' % (utils.URL, '1') + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body='{}', + headers={"Content-Type": "application/json", + "X-Auth-Token": self.disabled_token}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(403, int(resp['status'])) + + def test_get_baseURL_using_missing_auth_token(self): + header = httplib2.Http(".cache") + url = '%sbaseURLs/%s' % (utils.URL, '1') + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body='{}', + headers={"Content-Type": "application/json", + "X-Auth-Token": self.missing_token}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(401, int(resp['status'])) + + + def test_get_baseURL_using_invalid_auth_token(self): + header = httplib2.Http(".cache") + url = '%sbaseURLs/%s' % (utils.URL, '1') + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body='{}', + headers={"Content-Type": "application/json", + "X-Auth-Token": self.invalid_token}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(404, int(resp['status'])) + + def test_get_baseURL_xml(self): + header = httplib2.Http(".cache") + url = '%sbaseURLs/%s' % (utils.URL,'1') + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body='{}', + headers={"Content-Type": "application/xml", + "X-Auth-Token": self.auth_token, + "ACCEPT": "application/xml"}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(200, int(resp['status'])) + + #verify content + dom = etree.Element("root") + dom.append(etree.fromstring(content)) + baseURL = dom.find("{http://docs.openstack.org/identity/api/v2.0}" \ + "baseURL") + if baseURL == None: + self.fail("Expecting BaseURL") + + +class CreateBaseURLRefsTest(BaseURLsTest): + def test_baseurls_ref_create_json(self): + header = httplib2.Http(".cache") + resp, content = utils.create_baseurls_ref(self.tenant,"1", + str(self.auth_token)) + resp_val = int(resp['status']) + self.assertEqual(201, resp_val) + + def test_baseurls_ref_create_json_using_expired_token(self): + header = httplib2.Http(".cache") + resp, content = utils.create_baseurls_ref(self.tenant,"1", + str(self.exp_auth_token)) + resp_val = int(resp['status']) + self.assertEqual(403, resp_val) + + def test_baseurls_ref_create_json_using_disabled_token(self): + header = httplib2.Http(".cache") + resp, content = utils.create_baseurls_ref(self.tenant,"1", + str(self.disabled_token)) + resp_val = int(resp['status']) + self.assertEqual(403, resp_val) + + def test_baseurls_ref_create_json_using_missing_token(self): + header = httplib2.Http(".cache") + resp, content = utils.create_baseurls_ref(self.tenant,"1", + str(self.missing_token)) + resp_val = int(resp['status']) + self.assertEqual(401, resp_val) + + def test_baseurls_ref_create_json_using_invalid_token(self): + header = httplib2.Http(".cache") + resp, content = utils.create_baseurls_ref(self.tenant,"1", + str(self.invalid_token)) + resp_val = int(resp['status']) + self.assertEqual(404, resp_val) + + def test_baseurls_ref_create_xml(self): + header = httplib2.Http(".cache") + + resp, content = utils.create_baseurls_ref_xml(self.tenant,"1", + str(self.auth_token)) + resp_val = int(resp['status']) + self.assertEqual(201, resp_val) + url = '%stenants/%s/baseURLRefs/%s' % (URL, self.tenant, '1') + resp, content = header.request(url, "DELETE", body='', + headers={"Content-Type": "application/json", + "X-Auth-Token": str(self.auth_token)}) + resp_val = int(resp['status']) + self.assertEqual(204, resp_val) + + def test_baseurls_ref_create_xml_using_expired_token(self): + header = httplib2.Http(".cache") + + resp, content = utils.create_baseurls_ref_xml(self.tenant,"1", + str(self.auth_token)) + resp_val = int(resp['status']) + self.assertEqual(201, resp_val) + url = '%stenants/%s/baseURLRefs/%s' % (URL, self.tenant, '1') + resp, content = header.request(url, "DELETE", body='', + headers={"Content-Type": "application/json", + "X-Auth-Token": str(self.exp_auth_token)}) + resp_val = int(resp['status']) + self.assertEqual(403, resp_val) + + def test_baseurls_ref_create_xml_using_disabled_token(self): + header = httplib2.Http(".cache") + + resp, content = utils.create_baseurls_ref_xml(self.tenant,"1", + str(self.auth_token)) + resp_val = int(resp['status']) + self.assertEqual(201, resp_val) + url = '%stenants/%s/baseURLRefs/%s' % (URL, self.tenant, '1') + resp, content = header.request(url, "DELETE", body='', + headers={"Content-Type": "application/json", + "X-Auth-Token": str(self.disabled_token)}) + resp_val = int(resp['status']) + self.assertEqual(403, resp_val) + + def test_baseurls_ref_create_xml_using_missing_token(self): + header = httplib2.Http(".cache") + + resp, content = utils.create_baseurls_ref_xml(self.tenant,"1", + str(self.auth_token)) + resp_val = int(resp['status']) + self.assertEqual(201, resp_val) + url = '%stenants/%s/baseURLRefs/%s' % (URL, self.tenant, '1') + resp, content = header.request(url, "DELETE", body='', + headers={"Content-Type": "application/json", + "X-Auth-Token": str(self.missing_token)}) + resp_val = int(resp['status']) + self.assertEqual(401, resp_val) + + def test_baseurls_ref_create_xml_using_invalid_token(self): + header = httplib2.Http(".cache") + + resp, content = utils.create_baseurls_ref_xml(self.tenant,"1", + str(self.auth_token)) + resp_val = int(resp['status']) + self.assertEqual(201, resp_val) + url = '%stenants/%s/baseURLRefs/%s' % (URL, self.tenant, '1') + resp, content = header.request(url, "DELETE", body='', + headers={"Content-Type": "application/json", + "X-Auth-Token": str(self.invalid_token)}) + resp_val = int(resp['status']) + self.assertEqual(404, resp_val) + +class GetBaseURLRefsTest(BaseURLsTest): + def test_get_baseurls_ref_xml(self): + header = httplib2.Http(".cache") + url = '%stenants/%s/baseURLRefs' % (URL, self.tenant) + #test for Content-Type = application/xml + resp, content = header.request(url, "GET", body='{}', + headers={"Content-Type": "application/xml", + "X-Auth-Token": str(self.auth_token), + "ACCEPT": "application/xml"}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(200, int(resp['status'])) + + def test_get_baseurls_ref_xml_using_expired_auth_token(self): + header = httplib2.Http(".cache") + url = '%stenants/%s/baseURLRefs' % (URL, self.tenant) + #test for Content-Type = application/xml + resp, content = header.request(url, "GET", body='{}', + headers={"Content-Type": "application/xml", + "X-Auth-Token": str(self.exp_auth_token), + "ACCEPT": "application/xml"}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(403, int(resp['status'])) + + def test_get_baseurls_ref_xml_using_disabled_auth_token(self): + header = httplib2.Http(".cache") + url = '%stenants/%s/baseURLRefs' % (URL, self.tenant) + #test for Content-Type = application/xml + resp, content = header.request(url, "GET", body='{}', + headers={"Content-Type": "application/xml", + "X-Auth-Token": str(self.disabled_token), + "ACCEPT": "application/xml"}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(403, int(resp['status'])) + + def test_get_baseurls_ref_xml_using_missing_auth_token(self): + header = httplib2.Http(".cache") + url = '%stenants/%s/baseURLRefs' % (URL, self.tenant) + #test for Content-Type = application/xml + resp, content = header.request(url, "GET", body='{}', + headers={"Content-Type": "application/xml", + "X-Auth-Token": str(self.missing_token), + "ACCEPT": "application/xml"}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(401, int(resp['status'])) + + def test_get_baseurls_ref_xml_using_invalid_auth_token(self): + header = httplib2.Http(".cache") + url = '%stenants/%s/baseURLRefs' % (URL, self.tenant) + #test for Content-Type = application/xml + resp, content = header.request(url, "GET", body='{}', + headers={"Content-Type": "application/xml", + "X-Auth-Token": str(self.invalid_token), + "ACCEPT": "application/xml"}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(404, int(resp['status'])) + + def test_get_baseurls_ref_json(self): + header = httplib2.Http(".cache") + url = '%stenants/%s/baseURLRefs' % (URL, self.tenant) + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body='{}', + headers={"Content-Type": "application/json", + "X-Auth-Token": str(self.auth_token), + "ACCEPT": "application/json"}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(200, int(resp['status'])) + obj = json.loads(content) + if not "baseURLRefs" in obj: + raise self.fail("Expecting BaseURLRefs") + + def test_get_baseurls_ref_json_using_expired_auth_token(self): + header = httplib2.Http(".cache") + url = '%stenants/%s/baseURLRefs' % (URL, self.tenant) + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body='{}', + headers={"Content-Type": "application/json", + "X-Auth-Token": str(self.exp_auth_token), + "ACCEPT": "application/json"}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(403, int(resp['status'])) + obj = json.loads(content) + + def test_get_baseurls_ref_json_using_disabled_auth_token(self): + header = httplib2.Http(".cache") + url = '%stenants/%s/baseURLRefs' % (URL, self.tenant) + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body='{}', + headers={"Content-Type": "application/json", + "X-Auth-Token": str(self.disabled_token), + "ACCEPT": "application/json"}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(403, int(resp['status'])) + obj = json.loads(content) + + def test_get_baseurls_ref_json_using_missing_auth_token(self): + header = httplib2.Http(".cache") + url = '%stenants/%s/baseURLRefs' % (URL, self.tenant) + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body='{}', + headers={"Content-Type": "application/json", + "X-Auth-Token": str(self.missing_token), + "ACCEPT": "application/json"}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(401, int(resp['status'])) + obj = json.loads(content) + + def test_get_baseurls_ref_json_using_invalid_auth_token(self): + header = httplib2.Http(".cache") + url = '%stenants/%s/baseURLRefs' % (URL, self.tenant) + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body='{}', + headers={"Content-Type": "application/json", + "X-Auth-Token": str(self.invalid_token), + "ACCEPT": "application/json"}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(404, int(resp['status'])) + obj = json.loads(content) + +class DeleteBaseURLRefsTest(BaseURLsTest): + def test_delete_baseurlref(self): + header = httplib2.Http(".cache") + resp, content = utils.create_baseurls_ref(self.tenant,"1", + str(self.auth_token)) + resp_val = int(resp['status']) + self.assertEqual(201, resp_val) + obj = json.loads(content) + if not "baseURLRef" in obj: + raise fault.BadRequestFault("Expecting baseURLRef") + base_url_ref = obj["baseURLRef"] + if not "id" in base_url_ref: + base_url_ref_id = None + else: + base_url_ref_id = base_url_ref["id"] + if base_url_ref_id is None: + raise fault.BadRequestFault("Expecting baseURLRefID") + url = '%stenants/%s/baseURLRefs/%s' % (URL, self.tenant, base_url_ref_id) + resp, content = header.request(url, "DELETE", body='', + headers={"Content-Type": "application/json", + "X-Auth-Token": str(self.auth_token)}) + resp_val = int(resp['status']) + self.assertEqual(204, resp_val) + + def test_delete_baseurlref_using_expired_auth_token(self): + header = httplib2.Http(".cache") + resp, content = utils.create_baseurls_ref(self.tenant,"1", + str(self.auth_token)) + resp_val = int(resp['status']) + self.assertEqual(201, resp_val) + obj = json.loads(content) + if not "baseURLRef" in obj: + raise fault.BadRequestFault("Expecting baseURLRef") + base_url_ref = obj["baseURLRef"] + if not "id" in base_url_ref: + base_url_ref_id = None + else: + base_url_ref_id = base_url_ref["id"] + if base_url_ref_id is None: + raise fault.BadRequestFault("Expecting baseURLRefID") + url = '%stenants/%s/baseURLRefs/%s' % (URL, self.tenant, base_url_ref_id) + resp, content = header.request(url, "DELETE", body='', + headers={"Content-Type": "application/json", + "X-Auth-Token": str(self.exp_auth_token)}) + resp_val = int(resp['status']) + self.assertEqual(403, resp_val) + + def test_delete_baseurlref_using_disabled_auth_token(self): + header = httplib2.Http(".cache") + resp, content = utils.create_baseurls_ref(self.tenant,"1", + str(self.auth_token)) + resp_val = int(resp['status']) + self.assertEqual(201, resp_val) + obj = json.loads(content) + if not "baseURLRef" in obj: + raise fault.BadRequestFault("Expecting baseURLRef") + base_url_ref = obj["baseURLRef"] + if not "id" in base_url_ref: + base_url_ref_id = None + else: + base_url_ref_id = base_url_ref["id"] + if base_url_ref_id is None: + raise fault.BadRequestFault("Expecting baseURLRefID") + url = '%stenants/%s/baseURLRefs/%s' % (URL, self.tenant, base_url_ref_id) + resp, content = header.request(url, "DELETE", body='', + headers={"Content-Type": "application/json", + "X-Auth-Token": str(self.disabled_token)}) + resp_val = int(resp['status']) + self.assertEqual(403, resp_val) + + def test_delete_baseurlref_using_missing_auth_token(self): + header = httplib2.Http(".cache") + resp, content = utils.create_baseurls_ref(self.tenant,"1", + str(self.auth_token)) + resp_val = int(resp['status']) + self.assertEqual(201, resp_val) + obj = json.loads(content) + if not "baseURLRef" in obj: + raise fault.BadRequestFault("Expecting baseURLRef") + base_url_ref = obj["baseURLRef"] + if not "id" in base_url_ref: + base_url_ref_id = None + else: + base_url_ref_id = base_url_ref["id"] + if base_url_ref_id is None: + raise fault.BadRequestFault("Expecting baseURLRefID") + url = '%stenants/%s/baseURLRefs/%s' % (URL, self.tenant, base_url_ref_id) + resp, content = header.request(url, "DELETE", body='', + headers={"Content-Type": "application/json", + "X-Auth-Token": str(self.missing_token)}) + resp_val = int(resp['status']) + self.assertEqual(401, resp_val) + + def test_delete_baseurlref_using_invalid_auth_token(self): + header = httplib2.Http(".cache") + resp, content = utils.create_baseurls_ref(self.tenant,"1", + str(self.auth_token)) + resp_val = int(resp['status']) + self.assertEqual(201, resp_val) + obj = json.loads(content) + if not "baseURLRef" in obj: + raise fault.BadRequestFault("Expecting baseURLRef") + base_url_ref = obj["baseURLRef"] + if not "id" in base_url_ref: + base_url_ref_id = None + else: + base_url_ref_id = base_url_ref["id"] + if base_url_ref_id is None: + raise fault.BadRequestFault("Expecting baseURLRefID") + url = '%stenants/%s/baseURLRefs/%s' % (URL, self.tenant, base_url_ref_id) + resp, content = header.request(url, "DELETE", body='', + headers={"Content-Type": "application/json", + "X-Auth-Token": str(self.invalid_token)}) + resp_val = int(resp['status']) + self.assertEqual(404, resp_val) + +if __name__ == '__main__': + unittest.main() \ No newline at end of file diff --git a/keystone/test/unit/test_auth.py b/keystone/test/unit/test_auth.py new file mode 100644 index 00000000..e51cbbb6 --- /dev/null +++ b/keystone/test/unit/test_auth.py @@ -0,0 +1,34 @@ +import unittest +import os +import sys +import json + +sys.path.append(os.path.abspath(os.path.join(os.path.abspath(__file__), + '..', '..', '..', '..', 'keystone'))) + +from keystone import server +import keystone.logic.types.auth as auth +import keystone.logic.types.fault as fault + +from StringIO import StringIO +from datetime import date +from lxml import etree + + +class TestAuth(unittest.TestCase): + '''Unit tests for auth.py.''' + + pwd_xml = ' \ + ' + + def test_pwd_cred_marshall(self): + creds = auth.PasswordCredentials.from_xml(self.pwd_xml) + self.assertTrue(creds.password,"secret") + self.assertTrue(creds.username,"username") + + +if __name__ == '__main__': + unittest.main() \ No newline at end of file diff --git a/keystone/test/unit/test_authentication.py b/keystone/test/unit/test_authentication.py new file mode 100755 index 00000000..74089023 --- /dev/null +++ b/keystone/test/unit/test_authentication.py @@ -0,0 +1,215 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 +# Copyright (c) 2010-2011 OpenStack, LLC. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +import httplib2 +import json +from lxml import etree +import os +import sys +# Need to access identity module +sys.path.append(os.path.abspath(os.path.join(os.path.abspath(__file__), + '..', '..', '..', '..', 'keystone'))) +import unittest +from webtest import TestApp + +import test_common as utils + + +class AuthenticationTest(unittest.TestCase): + + def setUp(self): + self.tenant = utils.get_tenant() + self.token = utils.get_token('joeuser', 'secrete', self.tenant, + 'token') + #self.user = utils.get_user() + self.userdisabled = utils.get_userdisabled() + self.auth_token = utils.get_auth_token() + utils.create_baseurls_ref(self.tenant, "1", + str(self.auth_token)) + utils.create_baseurls_ref(self.tenant, "2", + str(self.auth_token)) + utils.create_baseurls_ref(self.tenant, "3", + str(self.auth_token)) + #self.exp_auth_token = utils.get_exp_auth_token() + #self.disabled_token = utils.get_disabled_token() + + def tearDown(self): + utils.delete_all_baseurls_ref(self.tenant, self.auth_token) + utils.delete_token(self.token, self.auth_token) + + def test_a_authorize(self): + resp, content = utils.get_token('joeuser', 'secrete', self.tenant) + self.assertEqual(200, int(resp['status'])) + obj = content + if not "auth" in obj: + raise fault.BadRequestFault("Expecting Auth") + auth = obj["auth"] + if not "serviceCatalog" in auth: + raise fault.BadRequestFault("Expecting Service Catalog") + + self.assertEqual('application/json', utils.content_type(resp)) + + def test_a_authorize_xml(self): + resp, content = utils.get_token_xml('joeuser', 'secrete', + self.tenant) + self.assertEqual(200, int(resp['status'])) + self.assertEqual('application/xml', utils.content_type(resp)) + #verify content + dom = etree.Element("root") + dom.append(etree.fromstring(content)) + auth = dom.find("{http://docs.openstack.org/identity/api/v2.0}" \ + "auth") + if auth == None: + self.fail("Expecting Auth") + service_catalog = auth.find( + "{http://docs.openstack.org/identity/api/v2.0}" \ + "serviceCatalog") + if service_catalog == None: + self.fail("Expecting Service Catalog") + + def test_a_authorize_legacy(self): + resp, content = utils.get_token_legacy('joeuser', 'secrete') + self.assertEqual(204, int(resp['status'])) + self.assertTrue(resp['x-auth-token']) + self.assertTrue(resp['x-server-management-url']) + self.assertTrue(resp['x-storage-url']) + self.assertTrue(resp['x-cdn-management-url']) + + def test_a_authorize_user_disabled(self): + header = httplib2.Http(".cache") + url = '%stokens' % utils.URL + body = {"passwordCredentials": {"username": self.userdisabled, + "password": "secrete", + "tenantId": self.tenant}} + resp, content = header.request(url, "POST", body=json.dumps(body), + headers={"Content-Type": "application/json"}) + + content = json.loads(content) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(403, int(resp['status'])) + self.assertEqual('application/json', utils.content_type(resp)) + + def test_a_authorize_user_disabled_xml(self): + header = httplib2.Http(".cache") + url = '%stokens' % utils.URL + body = ' \ + ' % (self.userdisabled, self.tenant) + resp, content = header.request(url, "POST", body=body, + headers={"Content-Type": "application/xml", + "ACCEPT": "application/xml"}) + + content = etree.fromstring(content) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(403, int(resp['status'])) + self.assertEqual('application/xml', utils.content_type(resp)) + + def test_a_authorize_user_wrong(self): + header = httplib2.Http(".cache") + url = '%stokens' % utils.URL + body = {"passwordCredentials": {"username-w": "disabled", + "password": "secrete", + "tenantId": self.tenant}} + resp, content = header.request(url, "POST", body=json.dumps(body), + headers={"Content-Type": "application/json"}) + content = json.loads(content) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(400, int(resp['status'])) + self.assertEqual('application/json', utils.content_type(resp)) + + def test_a_authorize_user_wrong_xml(self): + header = httplib2.Http(".cache") + url = '%stokens' % utils.URL + body = ' \ + ' % self.tenant + resp, content = header.request(url, "POST", body=body, + headers={"Content-Type": "application/xml", + "ACCEPT": "application/xml"}) + content = etree.fromstring(content) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(400, int(resp['status'])) + self.assertEqual('application/xml', utils.content_type(resp)) + + +class MultiToken(unittest.TestCase): + + def setUp(self): + self.auth_token = utils.get_auth_token() + self.userdisabled = utils.get_userdisabled() + resp1, content1 = utils.create_tenant('test_tenant1', self.auth_token) + #create tenant2 + resp2, content2 = utils.create_tenant('test_tenant2', self.auth_token) + #create user1 with tenant1 + resp3, content3 = utils.create_user('test_tenant1', 'test_user1', + self.auth_token) + resp3, content3 = utils.create_user('test_tenant1', 'test_user2', + self.auth_token) + #add user1 to tenant2 + resp4, content4 = utils.add_user_json('test_tenant2', 'test_user1', + self.auth_token) + #self.exp_auth_token = utils.get_exp_auth_token() + #self.disabled_token = utils.get_disabled_token() + + def tearDown(self): + utils.delete_user('test_tenant1', 'test_user1', self.auth_token) + utils.delete_user('test_tenant1', 'test_user2', self.auth_token) + utils.delete_user('test_tenant2', 'test_user1', self.auth_token) + utils.delete_tenant('test_tenant1', self.auth_token) + utils.delete_tenant('test_tenant2', self.auth_token) + + """ INVALID TEST - we're changing how we delegate access to second tenant + def test_multi_token(self): + #get token for user1 with tenant1 + token1 = utils.get_token('test_user1', 'secrete', 'test_tenant1',\ + 'token') + #get token for user 1 with tenant2 + token2 = utils.get_token('test_user1', 'secrete', 'test_tenant2',\ + 'token') + #test result :: both token should be different + self.assertNotEqual(token1, None) + self.assertNotEqual(token2, None) + self.assertNotEqual(token1, token2) + + resp = utils.delete_token(token1, self.auth_token) + resp = utils.delete_token(token2, self.auth_token) + """ + + def test_unassigned_user(self): + resp, content = utils.get_token('test_user2', 'secrete', \ + 'test_tenant') + + self.assertEqual(401, int(resp['status'])) + +if __name__ == '__main__': + unittest.main() diff --git a/keystone/test/unit/test_authn_v2.py b/keystone/test/unit/test_authn_v2.py new file mode 100644 index 00000000..af9d725b --- /dev/null +++ b/keystone/test/unit/test_authn_v2.py @@ -0,0 +1,463 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 +# Copyright (c) 2011 OpenStack, LLC. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import json +import logging + +from keystone import server +from test.unit import base +from test.unit.decorators import jsonify, xmlify + +logger = logging.getLogger('test.unit.test_authn_v2') + + +class AuthnMethods(object): + + def test_authn_get_fails(self): + """ + Test for GH issue #5. GET /tokens works when it should not + """ + url = "/tokens" + req = self.get_request('GET', url) + body = { + "passwordCredentials": { + "username": self.auth_user['id'], + "password": self.auth_user['password'], + "tenantId": self.auth_user['tenant_id'] + } + } + req.body = json.dumps(body) + self.get_response() + self.status_not_found() + + @jsonify + def test_authn_success_json(self): + """ + Test that good password credentials returns a 200 OK + """ + url = "/tokens" + req = self.get_request('POST', url) + body = { + "passwordCredentials": { + "username": self.auth_user['id'], + "password": self.auth_user['password'], + "tenantId": self.auth_user['tenant_id'] + } + } + req.body = json.dumps(body) + self.get_response() + self.status_ok() + + expected = { + u'auth': { + u'token': { + u'expires': self.expires.strftime("%Y-%m-%dT%H:%M:%S.%f"), + u'id': self.auth_token_id + } + } + } + self.assert_dict_equal(expected, json.loads(self.res.body)) + + @jsonify + def test_authn_success_missing_tenant_json(self): + """ + Test that supplying an existing user/pass, with a missing tenant ID + in the password credentials results in a 200 OK but a token not + matching the token with a tenant attached to it. + """ + # Create a special token for user with no tenant + auth_token = self.fixture_create_token( + user_id=self.auth_user['id'], + tenant_id=None, + expires=self.expires, + token_id='NOTENANTTOKEN') + + url = "/tokens" + req = self.get_request('POST', url) + body = { + "passwordCredentials": { + "username": self.auth_user['id'], + "password": self.auth_user['password'] + } + } + req.body = json.dumps(body) + self.get_response() + self.status_ok() + + expected = { + u'auth': { + u'token': { + u'expires': self.expires.strftime("%Y-%m-%dT%H:%M:%S.%f"), + u'id': 'NOTENANTTOKEN' + } + } + } + self.assert_dict_equal(expected, json.loads(self.res.body)) + + @jsonify + def test_authn_success_none_tenant_json(self): + """ + Test that supplying an existing user/pass, with a tenant ID of None + in the password credentials results in a 200 OK but a token not + matching the token with a tenant attached to it. + """ + # Create a special token for user with no tenant + auth_token = self.fixture_create_token( + user_id=self.auth_user['id'], + tenant_id=None, + expires=self.expires, + token_id='NOTENANTTOKEN') + + url = "/tokens" + req = self.get_request('POST', url) + body = { + "passwordCredentials": { + "username": self.auth_user['id'], + "password": self.auth_user['password'], + "tenantId": None + } + } + req.body = json.dumps(body) + self.get_response() + self.status_ok() + + expected = { + u'auth': { + u'token': { + u'expires': self.expires.strftime("%Y-%m-%dT%H:%M:%S.%f"), + u'id': 'NOTENANTTOKEN' + } + } + } + self.assert_dict_equal(expected, json.loads(self.res.body)) + + @jsonify + def test_authn_malformed_creds_json(self): + """ + Test that supplying a malformed password credentials + results in a 400 Bad Request + """ + url = "/tokens" + req = self.get_request('POST', url) + body = { + "passwordCredMisspelled": { + "username": 'unknown', + "password": 'badpass', + "tenantId": None + } + } + req.body = json.dumps(body) + self.get_response() + self.status_bad_request() + + @jsonify + def test_authn_user_not_found_json(self): + """ + Test that supplying a non-existing user in the password credentials + results in a 401 Unauthorized + """ + url = "/tokens" + req = self.get_request('POST', url) + body = { + "passwordCredentials": { + "username": 'unknown', + "password": 'badpass', + "tenantId": None + } + } + req.body = json.dumps(body) + self.get_response() + self.status_unauthorized() + + @jsonify + def test_authn_user_missing_json(self): + """ + Test that supplying a missing user in the password credentials + results in a 401 Unauthorized + """ + url = "/tokens" + req = self.get_request('POST', url) + body = { + "passwordCredentials": { + "username": None, + "password": self.auth_user['password'], + "tenantId": self.auth_user['tenant_id'] + } + } + req.body = json.dumps(body) + self.get_response() + self.status_unauthorized() + + @jsonify + def test_authn_bad_pass_json(self): + """ + Test that supplying an existing user and a bad password + in the password credentials results in a 401 Unauthorized + """ + url = "/tokens" + req = self.get_request('POST', url) + body = { + "passwordCredentials": { + "username": self.auth_user['id'], + "password": 'badpass', + "tenantId": None + } + } + req.body = json.dumps(body) + self.get_response() + self.status_unauthorized() + + @jsonify + def test_authn_bad_tenant_json(self): + """ + Test that supplying an existing user/pass, with a bad tenant ID + in the password credentials results in a 401 Unauthorized + """ + url = "/tokens" + req = self.get_request('POST', url) + body = { + "passwordCredentials": { + "username": self.auth_user['id'], + "password": self.auth_user['password'], + "tenantId": 'badtenant' + } + } + req.body = json.dumps(body) + self.get_response() + self.status_unauthorized() + + @xmlify + def test_authn_success_xml(self): + """ + Test that good password credentials returns a 200 OK + """ + url = "/tokens" + req = self.get_request('POST', url) + req.body = ' \ + ' % (self.auth_user['password'], + self.auth_user['id'], + self.auth_user['tenant_id']) + self.get_response() + self.status_ok() + + expected = """ + + + + """ % (self.expires.strftime("%Y-%m-%dT%H:%M:%S.%f"), + self.auth_token_id) + self.assert_xml_strings_equal(expected, self.res.body) + + @xmlify + def test_authn_success_missing_tenant_xml(self): + """ + Test that supplying an existing user/pass, with a missing tenant ID + in the password credentials results in a 200 OK but a token not + matching the token with a tenant attached to it. + """ + # Create a special token for user with no tenant + auth_token = self.fixture_create_token( + user_id=self.auth_user['id'], + tenant_id=None, + expires=self.expires, + token_id='NOTENANTTOKEN') + + url = "/tokens" + req = self.get_request('POST', url) + req.body = ' \ + ' % ( + self.auth_user['password'], + self.auth_user['id']) + self.get_response() + self.status_ok() + + expected = """ + + + + """ % (self.expires.strftime("%Y-%m-%dT%H:%M:%S.%f"), + 'NOTENANTTOKEN') + self.assert_xml_strings_equal(expected, self.res.body) + + @xmlify + def test_authn_malformed_creds_xml(self): + """ + Test that supplying a malformed password credentials + results in a 400 Bad Request + """ + url = "/tokens" + req = self.get_request('POST', url) + req.body = ' \ + ' % (self.auth_user['password'], + self.auth_user['id'], + self.auth_user['tenant_id']) + self.get_response() + self.status_bad_request() + + @xmlify + def test_authn_user_not_found_xml(self): + """ + Test that supplying a non-existing user in the password credentials + results in a 401 Unauthorized + """ + url = "/tokens" + req = self.get_request('POST', url) + req.body = ' \ + ' % (self.auth_user['password'], + 'missinguser', + self.auth_user['tenant_id']) + self.get_response() + self.status_unauthorized() + + @xmlify + def test_authn_user_missing_xml(self): + """ + Test that supplying a missing user in the password credentials + results in a 400 Bad Request + """ + url = "/tokens" + req = self.get_request('POST', url) + req.body = ' \ + ' % (self.auth_user['password'], + self.auth_user['tenant_id']) + self.get_response() + self.status_bad_request() + + @xmlify + def test_authn_bad_pass_xml(self): + """ + Test that supplying a bad password in the password credentials + results in a 401 Unauthorized + """ + url = "/tokens" + req = self.get_request('POST', url) + req.body = ' \ + ' % ('badpass', + self.auth_user['id'], + self.auth_user['tenant_id']) + self.get_response() + self.status_unauthorized() + + @xmlify + def test_authn_bad_tenant_xml(self): + """ + Test that supplying a bad tenant in the password credentials + results in a 401 Unauthorized + """ + url = "/tokens" + req = self.get_request('POST', url) + req.body = ' \ + ' % (self.auth_user['password'], + self.auth_user['id'], + 'badtenant') + self.get_response() + self.status_unauthorized() + + +class TestAuthnV2(base.ServiceAPITest, AuthnMethods): + + """ + Tests for the /v2.0/tokens auth endpoint with main service API + """ + + +class TestAdminAuthnV2(base.AdminAPITest, AuthnMethods): + + """ + Tests for the /v2.0/tokens auth endpoint with admin API + """ + + @jsonify + def test_validate_token_json(self): + """ + Test successful validation of the token we use in authn + """ + url = "/tokens/%s" % self.auth_token_id + headers = {"X-Auth-Token": self.auth_token_id} + req = self.get_request('GET', url, headers) + self.get_response() + self.status_ok() + + expected = { + "auth": { + "token": { + u'expires': self.expires.strftime("%Y-%m-%dT%H:%M:%S.%f"), + u'id': self.auth_token_id, + "tenantId": self.auth_user['tenant_id'] + }, + "user": { + "username": self.auth_user['id'], + "tenantId": self.auth_user['tenant_id'], + "roleRefs": [] + } + } + } + for user_role in self.auth_user['roles']: + expected["auth"]["user"]["roleRefs"].append( + {"roleId": user_role['role_id'], "id": user_role['id']}) + self.assert_dict_equal(expected, json.loads(self.res.body)) + + @xmlify + def test_validate_token_xml(self): + """ + Test successful validation of the token we use in authn + """ + url = "/tokens/%s" % self.auth_token_id + headers = {"X-Auth-Token": self.auth_token_id} + req = self.get_request('GET', url, headers) + self.get_response() + self.status_ok() + + expected = """ + + + + """ % ( + self.expires.strftime("%Y-%m-%dT%H:%M:%S.%f"), + self.auth_token_id, + self.auth_user['tenant_id'], + self.auth_user['id'], + self.auth_user['tenant_id']) + + for user_role in self.auth_user['roles']: + expected = expected + """ + """ % (user_role['id'], + user_role['role_id']) + expected = expected + """ + + """ + self.assert_xml_strings_equal(expected, self.res.body) diff --git a/keystone/test/unit/test_common.py b/keystone/test/unit/test_common.py new file mode 100755 index 00000000..be017285 --- /dev/null +++ b/keystone/test/unit/test_common.py @@ -0,0 +1,809 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 +# Copyright (c) 2010-2011 OpenStack, LLC. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +import httplib2 +import json +from lxml import etree +import os +import sys +sys.path.append(os.path.abspath(os.path.join(os.path.abspath(__file__), + '..', '..', '..', '..', 'keystone'))) +import unittest + +URL = 'http://localhost:8081/v2.0/' +URLv1 = 'http://localhost:8080/v1.0/' + +def get_token(user, pswd, tenant_id, kind=''): + header = httplib2.Http(".cache") + url = '%stokens' % URL + + if not tenant_id: + body = {"passwordCredentials": {"username": user, + "password": pswd}} + else: + body = {"passwordCredentials": {"username": user, + "password": pswd, + "tenantId": tenant_id}} + + resp, content = header.request(url, "POST", body=json.dumps(body), + headers={"Content-Type": "application/json"}) + + if int(resp['status']) == 200: + content = json.loads(content) + token = str(content['auth']['token']['id']) + else: + token = None + if kind == 'token': + return token + else: + return (resp, content) + + +def get_token_legacy(user, pswd, kind=''): + header = httplib2.Http(".cache") + url = URLv1 + resp, content = header.request(url, "GET", '', + headers={"Content-Type": "application/json", + "X-Auth-User": user, + "X-Auth-Key": pswd}) + + if int(resp['status']) == 204: + token = resp['x-auth-token'] + else: + token = None + if kind == 'token': + return token + else: + return (resp, content) + + +def delete_token(token, auth_token): + header = httplib2.Http(".cache") + url = '%stoken/%s' % (URL, token) + resp, content = header.request(url, "DELETE", body='', + headers={"Content-Type": "application/json", + "X-Auth-Token": auth_token}) + return (resp, content) + + +def create_tenant(tenantid, auth_token): + header = httplib2.Http(".cache") + + url = '%stenants' % (URL) + body = {"tenant": {"id": tenantid, + "description": "A description ...", + "enabled": True}} + resp, content = header.request(url, "POST", body=json.dumps(body), + headers={"Content-Type": "application/json", + "X-Auth-Token": auth_token}) + return (resp, content) + + +def create_tenant_group(groupid, tenantid, auth_token): + header = httplib2.Http(".cache") + + url = '%stenants/%s/groups' % (URL, tenantid) + body = {"group": {"id": groupid, + "description": "A description ..."}} + resp, content = header.request(url, "POST", body=json.dumps(body), + headers={"Content-Type": "application/json", + "X-Auth-Token": auth_token}) + return (resp, content) + + +def delete_tenant(tenantid, auth_token): + header = httplib2.Http(".cache") + url = '%stenants/%s' % (URL, tenantid) + resp, content = header.request(url, "DELETE", body='{}', + headers={"Content-Type": "application/json", + "X-Auth-Token": auth_token}) + return resp + + +def delete_tenant_group(groupid, tenantid, auth_token): + header = httplib2.Http(".cache") + url = '%stenants/%s/groups/%s' % (URL, tenantid, groupid) + resp, content = header.request(url, "DELETE", body='{}', + headers={"Content-Type": "application/json", + "X-Auth-Token": auth_token}) + return (resp, content) + + +def create_global_group(groupid, auth_token): + header = httplib2.Http(".cache") + + url = '%sgroups' % (URL) + body = {"group": {"id": groupid, + "description": "A description ..."}} + resp, content = header.request(url, "POST", body=json.dumps(body), + + headers={"Content-Type": "application/json", + "X-Auth-Token": auth_token}) + return (resp, content) + + +def create_global_group_xml(groupid, auth_token): + header = httplib2.Http(".cache") + url = '%sgroups' % (URL) + body = '\ + A Description of the group\ + ' % groupid + resp, content = header.request(url, "POST", body=body, + headers={"Content-Type": "application/xml", + "X-Auth-Token": auth_token, + "ACCEPT": "application/xml"}) + return (resp, content) + + +def delete_global_group(groupid, auth_token): + header = httplib2.Http(".cache") + url = '%sgroups/%s' % (URL, groupid) + resp, content = header.request(url, "DELETE", body='{}', + headers={"Content-Type": "application/json", + "X-Auth-Token": auth_token}) + return (resp, content) + + +def delete_global_group_xml(groupid, auth_token): + header = httplib2.Http(".cache") + url = '%sgroups/%s' % (URL, groupid) + resp, content = header.request(url, "DELETE", body='', + headers={"Content-Type": "application/xml", + "X-Auth-Token": auth_token, + "ACCEPT": "application/xml"}) + return (resp, content) + + +def get_token_xml(user, pswd, tenant_id, type=''): + header = httplib2.Http(".cache") + url = '%stokens' % URL + # to test multi token, removing below code + """if tenant_id: + body = ' \ + ' % (pswd, user, tenant_id) + else: + body = ' \ + ' % (pswd, user)""" + # adding code ie., body + body = ' \ + ' % (pswd, user, tenant_id) + resp, content = header.request(url, "POST", body=body, + headers={"Content-Type": "application/xml", + "ACCEPT": "application/xml"}) + if int(resp['status']) == 200: + dom = etree.fromstring(content) + root = dom.find("{http://docs.openstack.org/" \ + "identity/api/v2.0}token") + token_root = root.attrib + token = str(token_root['id']) + else: + token = None + + if type == 'token': + return token + else: + return (resp, content) + + +def delete_token_xml(token, auth_token): + header = httplib2.Http(".cache") + url = '%stoken/%s' % (URL, token) + resp, content = header.request(url, "DELETE", body='', + headers={"Content-Type": "application/xml", + "X-Auth-Token": auth_token, + "ACCEPT": "application/xml"}) + return (resp, content) + + +def create_tenant_xml(tenantid, auth_token): + header = httplib2.Http(".cache") + url = '%stenants' % (URL) + body = ' \ + \ + A description... \ + ' % tenantid + resp, content = header.request(url, "POST", body=body, + headers={"Content-Type": "application/xml", + "X-Auth-Token": auth_token, + "ACCEPT": "application/xml"}) + return (resp, content) + + +def create_tenant_group_xml(groupid, tenantid, auth_token): + header = httplib2.Http(".cache") + url = '%stenants/%s/groups' % (URL, tenantid) + body = ' \ + \ + A description... \ + ' % groupid + resp, content = header.request(url, "POST", body=body, + headers={"Content-Type": "application/xml", + "X-Auth-Token": auth_token, + "ACCEPT": "application/xml"}) + return (resp, content) + + +def delete_tenant_xml(tenantid, auth_token): + header = httplib2.Http(".cache") + url = '%stenants/%s' % (URL, tenantid) + resp, content = header.request(url, "DELETE", body='', + headers={"Content-Type": "application/xml", + "X-Auth-Token": auth_token, + "ACCEPT": "application/xml"}) + + return resp + + +def delete_tenant_group_xml(groupid, tenantid, auth_token): + header = httplib2.Http(".cache") + url = '%stenant/%s/groups/%s' % (URL, tenantid, groupid) + resp, content = header.request(url, "DELETE", body='', + headers={"Content-Type": "application/xml", + "X-Auth-Token": auth_token, + "ACCEPT": "application/xml"}) + return (resp, content) + + +def create_user(tenantid, userid, auth_token, email=None): + header = httplib2.Http(".cache") + url = '%stenants/%s/users' % (URL, tenantid) + if email is not None: + email_id = email + else: + email_id = "%s@rackspace.com" % userid + body = {"user": {"password": "secrete", + "id": userid, + "tenantId": tenantid, + "email": "%s" % email_id, + "enabled": True}} + resp, content = header.request(url, "POST", body=json.dumps(body), + headers={"Content-Type": "application/json", + "X-Auth-Token": auth_token}) + return (resp, content) + + +def delete_user(tenant, userid, auth_token): + header = httplib2.Http(".cache") + url = '%stenants/%s/users/%s' % (URL, tenant, userid) + resp, content = header.request(url, "DELETE", body='{}', + headers={"Content-Type": "application/json", + "X-Auth-Token": auth_token}) + return resp + + +def create_user_xml(tenantid, userid, auth_token, email=None): + header = httplib2.Http(".cache") + url = '%stenants/%s/users' % (URL, tenantid) + if email is not None: + email_id = email + else: + email_id = userid + body = ' \ + ' % (email_id, tenantid, userid) + resp, content = header.request(url, "POST", body=body, + headers={"Content-Type": "application/xml", + "X-Auth-Token": auth_token, + "ACCEPT": "application/xml"}) + return (resp, content) + + +"""def delete_user(tenant, userid, auth_token): + h = httplib2.Http(".cache") + url = '%stenants/%s/users/%s' % (URL, tenant, userid) + + resp, content = h.request(url, "DELETE", body='{}', + headers={"Content-Type": "application/json", + "X-Auth-Token": auth_token}) + return resp""" + + +def delete_user_xml(tenantid, userid, auth_token): + header = httplib2.Http(".cache") + url = '%stenants/%s/users/%s' % (URL, tenantid, userid) + resp, content = header.request(url, "DELETE", body='', + headers={"Content-Type": "application/xml", + "X-Auth-Token": auth_token, + "ACCEPT": "application/xml"}) + return resp + + +def add_user_json(tenantid, userid, auth_token): + header = httplib2.Http(".cache") + url = '%stenants/%s/users/%s/add' % (URL, tenantid, userid) + resp, content = header.request(url, "PUT", body='{}', + headers={"Content-Type": "application/json", + "X-Auth-Token": auth_token}) + return (resp, content) + +def add_user_xml(tenantid, userid, auth_token): + header = httplib2.Http(".cache") + url = '%stenants/%s/users/%s/add' % (URL, tenantid, userid) + resp, content = header.request(url, "PUT", body='{}', + headers={"Content-Type": "application/xml", + "X-Auth-Token": auth_token, + "ACCEPT": "application/xml"}) + return (resp, content) + +def add_user_json(tenantid, userid, auth_token): + header = httplib2.Http(".cache") + url = '%stenants/%s/users/' % (URL, tenantid) + resp, content = header.request(url, "POST", body='{}', + headers={"Content-Type": "application/json", + "X-Auth-Token": auth_token}) + return (resp, content) + + +def add_user_xml(tenantid, userid, auth_token): + header = httplib2.Http(".cache") + url = '%stenants/%s/users/%s/add' % (URL, tenantid, userid) + resp, content = header.request(url, "PUT", body='{}', + headers={"Content-Type": "application/xml", + "X-Auth-Token": auth_token, + "ACCEPT": "application/xml"}) + return (resp, content) + + +def user_update_json(tenant_id, user_id, auth_token, email=None): + h = httplib2.Http(".cache") + url = '%stenants/%s/users/%s' % (URL, tenant_id, user_id) + if email is None: + new_email = "updatedjoeuser@rackspace.com" + else: + new_email = email + data = '{"user": { "email": "%s"}}' % (new_email) + resp, content = h.request(url, "PUT", body=data, + headers={"Content-Type": "application/json", + "X-Auth-Token": auth_token}) + return (resp, content) + + +def user_update_xml(tenant_id, user_id, auth_token, email=None): + h = httplib2.Http(".cache") + url = '%stenants/%s/users/%s' % (URL, tenant_id, user_id) + if email is None: + new_email = "updatedjoeuser@rackspace.com" + else: + new_email = email + data = ' \ + ' % (new_email) + resp, content = h.request(url, "PUT", body=data, + headers={"Content-Type": "application/xml", + "X-Auth-Token": auth_token, + "ACCEPT": "application/xml"}) + return (resp, content) + + +def user_get_json(tenant_id, user_id, auth_token): + h = httplib2.Http(".cache") + url = '%stenants/%s/users/%s' % (URL, tenant_id, user_id) + #test for Content-Type = application/json + resp, content = h.request(url, "GET", body='{}', + headers={"Content-Type": "application/json", + "X-Auth-Token": auth_token}) + return (resp, content) + + +def user_password_json(tenant_id, user_id, auth_token): + h = httplib2.Http(".cache") + url = '%stenants/%s/users/%s/password' % (URL, tenant_id, user_id) + data = '{"user": { "password": "p@ssword"}}' + resp, content = h.request(url, "PUT", body=data, + headers={"Content-Type": "application/json", + "X-Auth-Token": auth_token}) + return (resp, content) + + +def user_password_xml(tenant_id, user_id, auth_token): + h = httplib2.Http(".cache") + url = '%stenants/%s/users/%s/password' % (URL, tenant_id, user_id) + data = ' \ + ' + resp, content = h.request(url, "PUT", body=data, + headers={"Content-Type": "application/xml", + "X-Auth-Token": auth_token, + "ACCEPT": "application/xml"}) + return (resp, content) + + +def user_enabled_json(tenant_id, user_id, auth_token): + h = httplib2.Http(".cache") + url = '%stenants/%s/users/%s/enabled' % (URL, tenant_id, user_id) + data = {"user": {"enabled": True}} + resp, content = h.request(url, "PUT", body=json.dumps(data), + headers={"Content-Type": "application/json", + "X-Auth-Token": auth_token}) + return (resp, content) + + +def user_enabled_xml(tenant_id, user_id, auth_token): + h = httplib2.Http(".cache") + url = '%stenants/%s/users/%s/enabled' % (URL, tenant_id, user_id) + data = ' \ + ' + resp, content = h.request(url, "PUT", body=data, + headers={"Content-Type": "application/xml", + "X-Auth-Token": auth_token, + "ACCEPT": "application/xml"}) + return (resp, content) + + +def user_get_xml(tenant_id, user_id, auth_token): + h = httplib2.Http(".cache") + url = '%stenants/%s/users/%s' % (URL, tenant_id, user_id) + resp, content = h.request(url, "GET", body='{}', + headers={"Content-Type": "application/xml", + "X-Auth-Token": auth_token, + "ACCEPT": "application/xml"}) + return (resp, content) + + +def users_get_json(tenant_id, auth_token): + h = httplib2.Http(".cache") + url = '%stenants/%s/users' % (URL, tenant_id) + resp, content = h.request(url, "GET", body='{}', + headers={"Content-Type": "application/json", + "X-Auth-Token": auth_token}) + return (resp, content) + + +def users_get_xml(tenant_id, auth_token): + h = httplib2.Http(".cache") + url = '%stenants/%s/users' % (URL, tenant_id) + resp, content = h.request(url, "GET", body='{}', + headers={"Content-Type": "application/xml", + "X-Auth-Token": auth_token, + "ACCEPT": "application/xml"}) + return (resp, content) + + +def users_group_get_json(tenant_id, user_id, auth_token): + h = httplib2.Http(".cache") + url = '%stenants/%s/users/%s/groups' % (URL, tenant_id, user_id) + resp, content = h.request(url, "GET", body='{}', + headers={"Content-Type": "application/json", + "X-Auth-Token": auth_token}) + return (resp, content) + + +def users_group_get_xml(tenant_id, user_id, auth_token): + h = httplib2.Http(".cache") + url = '%stenants/%s/users/%s/groups' % (URL, tenant_id, user_id) + resp, content = h.request(url, "GET", body='{}', + headers={"Content-Type": "application/xml", + "X-Auth-Token": auth_token, + "ACCEPT": "application/xml"}) + return (resp, content) + + +def add_user_tenant_group(tenantid, groupid, userid, auth_token): + header = httplib2.Http(".cache") + url = '%stenants/%s/groups/%s/users/%s' % (URL, tenantid, groupid, userid) + + resp, content = header.request(url, "PUT", body='', + headers={"Content-Type": "application/json", + "X-Auth-Token": auth_token}) + return (resp, content) + + +def add_user_tenant_group_xml(tenantid, groupid, userid, auth_token): + header = httplib2.Http(".cache") + url = '%stenants/%s/groups/%s/users/%s' % (URL, tenantid, groupid, userid) + + resp, content = header.request(url, "PUT", body='', + headers={"Content-Type": "application/xml", + "X-Auth-Token": auth_token, + "ACCEPT": "application/xml"}) + return (resp, content) + + +def delete_user_tenant_group(tenantid, groupid, userid, auth_token): + header = httplib2.Http(".cache") + url = '%stenants/%s/groups/%s/users/%s' % (URL, tenantid, groupid, userid) + + resp, content = header.request(url, "DELETE", body='', + headers={"Content-Type": "application/json", + "X-Auth-Token": auth_token}) + return (resp, content) + + +def delete_user_tenant_group_xml(tenantid, groupid, userid, auth_token): + header = httplib2.Http(".cache") + url = '%stenants/%s/groups/%s/users/%s' % (URL, tenantid, groupid, userid) + + resp, content = header.request(url, "DELETE", body='', + headers={"Content-Type": "application/xml", + "X-Auth-Token": auth_token, + "ACCEPT": "application/xml"}) + return (resp, content) + + +def get_user_tenant_group(tenantid, groupid, auth_token): + header = httplib2.Http(".cache") + url = '%stenants/%s/groups/%s/users' % (URL, tenantid, groupid) + + resp, content = header.request(url, "GET", body='', + headers={"Content-Type": "application/json", + "X-Auth-Token": auth_token}) + return (resp, content) + + +def get_user_tenant_group_xml(tenantid, groupid, auth_token): + header = httplib2.Http(".cache") + url = '%stenants/%s/groups/%s/users' % (URL, tenantid, groupid) + + resp, content = header.request(url, "GET", body='', + headers={"Content-Type": "application/xml", + "X-Auth-Token": auth_token, + "ACCEPT": "application/xml"}) + return (resp, content) + + +def add_user_global_group(groupid, userid, auth_token): + header = httplib2.Http(".cache") + url = '%sgroups/%s/users/%s' % (URL, groupid, userid) + + resp, content = header.request(url, "PUT", body='', + headers={"Content-Type": "application/json", + "X-Auth-Token": auth_token}) + return (resp, content) + + +def add_user_global_group_xml(groupid, userid, auth_token): + header = httplib2.Http(".cache") + url = '%sgroups/%s/users/%s' % (URL, groupid, userid) + + resp, content = header.request(url, "PUT", body='', + headers={"Content-Type": "application/xml", + "X-Auth-Token": auth_token, + "ACCEPT": "application/xml"}) + return (resp, content) + + +def delete_user_global_group(groupid, userid, auth_token): + header = httplib2.Http(".cache") + url = '%sgroups/%s/users/%s' % (URL, groupid, userid) + + resp, content = header.request(url, "DELETE", body='', + headers={"Content-Type": "application/json", + "X-Auth-Token": auth_token}) + return (resp, content) + + +def delete_user_global_group_xml(groupid, userid, auth_token): + header = httplib2.Http(".cache") + url = '%sgroups/%s/users/%s' % (URL, groupid, userid) + + resp, content = header.request(url, "DELETE", body='', + headers={"Content-Type": "application/xml", + "X-Auth-Token": auth_token, + "ACCEPT": "application/xml"}) + return (resp, content) + + +def get_user_global_group(groupid, auth_token): + header = httplib2.Http(".cache") + url = '%sgroups/%s/users' % (URL, groupid) + + resp, content = header.request(url, "GET", body='', + headers={"Content-Type": "application/json", + "X-Auth-Token": auth_token}) + + return (resp, content) + + +def get_userid(): + return 'test_user11' + + +def get_password(): + return 'secrete' + + +def get_email(): + return 'joetest@rackspace.com' + + +def get_user_global_group_xml(groupid, auth_token): + header = httplib2.Http(".cache") + url = '%sgroups/%s/users' % (URL, groupid) + + resp, content = header.request(url, "GET", body='', + headers={"Content-Type": "application/xml", + "X-Auth-Token": auth_token, + "ACCEPT": "application/xml"}) + return (resp, content) + + +def get_tenant(): + return '1234' + + +def get_another_tenant(): + return '4321' + + +def get_user(): + return 'test_user' + + +def get_userdisabled(): + return 'disabled' + + +def get_auth_token(): + return '999888777666' + + +def get_exp_auth_token(): + return '000999' + + +def get_none_token(): + return '' + + +def get_non_existing_token(): + return 'invalid_token' + + +def get_disabled_token(): + return '999888777' + + +def content_type(resp): + return resp['content-type'].split(';')[0] + + +def get_global_tenant(): + return 'GlobalTenant' + + +def handle_user_resp(self, content, respvalue, resptype): + if respvalue == 200: + if resptype == 'application/json': + content = json.loads(content) + if 'tenantId' in content['user']: + self.tenant = content['user']['tenantId'] + self.userid = content['user']['id'] + if resptype == 'application/xml': + content = etree.fromstring(content) + self.tenant = content.get("tenantId") + self.id = content.get("id") + if respvalue == 500: + self.fail('Identity Fault') + elif respvalue == 503: + self.fail('Service Not Available') + +def create_role(roleid, auth_token): + header = httplib2.Http(".cache") + + url = '%sroles' % (URL) + body = {"role": {"id": roleid, + "description": "A description ..."}} + resp, content = header.request(url, "POST", body=json.dumps(body), + headers={"Content-Type": "application/json", + "X-Auth-Token": auth_token}) + return (resp, content) + +def create_role_ref(user_id, role_id, tenant_id, auth_token): + header = httplib2.Http(".cache") + + url = '%susers/%s/roleRefs' % (URL, user_id) + body = {"roleRef": {"tenantId": tenant_id, + "roleId": role_id}} + resp, content = header.request(url, "POST", body=json.dumps(body), + headers={"Content-Type": "application/json", + "X-Auth-Token": auth_token}) + return (resp, content) + +def create_role_ref_xml(user_id, role_id, tenant_id, auth_token): + header = httplib2.Http(".cache") + url = '%susers/%s/roleRefs' % (URL, user_id) + body = '\ + \ + ' % (tenant_id, role_id) + resp, content = header.request(url, "POST", body=body, + headers={"Content-Type": "application/xml", + "X-Auth-Token": auth_token, + "ACCEPT": "application/xml"}) + return (resp, content) + +def delete_role_ref(user, role_ref_id, auth_token): + header = httplib2.Http(".cache") + url = '%susers/%s/roleRefs/%s' % (URL, user, role_ref_id) + resp, content = header.request(url, "DELETE", body='', + headers={"Content-Type": "application/json", + "X-Auth-Token": str(auth_token)}) + return (resp, content) + +def create_role_xml(role_id, auth_token): + header = httplib2.Http(".cache") + url = '%sroles' % (URL) + body = '\ + \ + ' % role_id + resp, content = header.request(url, "POST", body=body, + headers={"Content-Type": "application/xml", + "X-Auth-Token": auth_token, + "ACCEPT": "application/xml"}) + return (resp, content) + +def create_baseurls_ref(tenant_id, baseurl_id, auth_token): + header = httplib2.Http(".cache") + + url = '%stenants/%s/baseURLRefs' % (URL, tenant_id) + body = {"baseURL": {"id": baseurl_id}} + resp, content = header.request(url, "POST", body=json.dumps(body), + headers={"Content-Type": "application/json", + "X-Auth-Token": auth_token}) + return (resp, content) + +def create_baseurls_ref_xml(tenant_id, baseurl_id, auth_token): + header = httplib2.Http(".cache") + url = '%stenants/%s/baseURLRefs' % (URL, tenant_id) + body = '\ + \ + ' % (baseurl_id) + resp, content = header.request(url, "POST", body=body, + headers={"Content-Type": "application/xml", + "X-Auth-Token": auth_token, + "ACCEPT": "application/xml"}) + return (resp, content) + +def delete_all_baseurls_ref(tenant_id, auth_token): + header = httplib2.Http(".cache") + url = '%stenants/%s/baseURLRefs' % (URL, tenant_id) + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body='{}', + headers={"Content-Type": "application/json", + "X-Auth-Token": auth_token}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + + #verify content + obj = json.loads(content) + base_url_refs = obj["baseURLRefs"]["values"] + for base_url_ref in base_url_refs: + url = '%stenants/%s/baseURLRefs/%s' % (URL, tenant_id, base_url_ref["id"]) + header.request(url, "DELETE", body='', + headers={"Content-Type": "application/json", + "X-Auth-Token": str(auth_token)}) + +if __name__ == '__main__': + unittest.main() \ No newline at end of file diff --git a/keystone/test/unit/test_exthandler.py b/keystone/test/unit/test_exthandler.py new file mode 100644 index 00000000..4379e03f --- /dev/null +++ b/keystone/test/unit/test_exthandler.py @@ -0,0 +1,65 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 +# Copyright (c) 2010-2011 OpenStack, LLC. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +import os +import sys +# Need to access identity module +sys.path.append(os.path.abspath(os.path.join( + os.getcwd(), '..', '..', 'keystone'))) +from queryext.exthandler import UrlExtensionFilter +import unittest + + +class MockWsgiApp(object): + + def __init__(self): + pass + + def __call__(self, env, start_response): + pass + + +def _start_response(): + pass + + +class UrlExtensionFilterTest(unittest.TestCase): + + def setUp(self): + self.filter = UrlExtensionFilter(MockWsgiApp(), {}) + + def test_xml_extension(self): + env = {'PATH_INFO': '/v2.0/someresource.xml'} + self.filter(env, _start_response) + self.assertEqual('/v2.0/someresource', env['PATH_INFO']) + self.assertEqual('application/xml', env['HTTP_ACCEPT']) + + def test_json_extension(self): + env = {'PATH_INFO': '/v2.0/someresource.json'} + self.filter(env, _start_response) + self.assertEqual('/v2.0/someresource', env['PATH_INFO']) + self.assertEqual('application/json', env['HTTP_ACCEPT']) + + def test_extension_overrides_header(self): + env = {'PATH_INFO': '/v2.0/someresource.json', + 'HTTP_ACCEPT': 'application/xml'} + self.filter(env, _start_response) + self.assertEqual('/v2.0/someresource', env['PATH_INFO']) + self.assertEqual('application/json', env['HTTP_ACCEPT']) + + +if __name__ == '__main__': + unittest.main() diff --git a/keystone/test/unit/test_groups.py b/keystone/test/unit/test_groups.py new file mode 100644 index 00000000..2d7a7e00 --- /dev/null +++ b/keystone/test/unit/test_groups.py @@ -0,0 +1,966 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 +# Copyright (c) 2010-2011 OpenStack, LLC. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +import httplib2 +import json +from lxml import etree +import os +import sys +sys.path.append(os.path.abspath(os.path.join(os.path.abspath(__file__), + '..', '..', '..', '..', 'keystone'))) +import unittest +from webtest import TestApp + +import test_common as utils + + +## +## Global Group Tests +## + + +class GlobalGroupTest(unittest.TestCase): + + def setUp(self): + self.globaltenant = utils.get_global_tenant() + self.user = utils.get_user() + self.userdisabled = utils.get_userdisabled() + self.auth_token = utils.get_auth_token() + self.exp_auth_token = utils.get_exp_auth_token() + self.disabled_token = utils.get_disabled_token() + self.global_group = 'test_global_group_add' + utils.create_tenant(self.globaltenant, str(self.auth_token)) + utils.create_user(self.globaltenant, self.user, self.auth_token) + utils.add_user_json(self.globaltenant, self.user, self.auth_token) + self.token = utils.get_token(self.user, 'secrete', self.globaltenant, + 'token') + + def tearDown(self): + utils.delete_user(self.globaltenant, self.user, str(self.auth_token)) + utils.delete_global_group(self.global_group, self.auth_token) + utils.delete_tenant(self.globaltenant, self.auth_token) + + +class CreateGlobalGroupTest(GlobalGroupTest): + + def test_global_group_create(self): + utils.delete_global_group(self.global_group, str(self.auth_token)) + resp_new, content_new = utils.create_global_group(self.global_group, + str(self.auth_token)) + + if int(resp_new['status']) == 500: + self.fail('Identity fault') + elif int(resp_new['status']) == 503: + self.fail('Service Not Available') + if int(resp_new['status']) not in (200, 201): + self.fail('Failed due to %d' % int(resp_new['status'])) + + def test_global_group_create_xml(self): + utils.delete_global_group_xml(self.global_group, str(self.auth_token)) + resp_new, content_new = utils.create_global_group_xml(\ + self.global_group, + str(self.auth_token)) + + if int(resp_new['status']) == 500: + self.fail('Identity fault') + elif int(resp_new['status']) == 503: + self.fail('Service Not Available') + + if int(resp_new['status']) not in (200, 201): + self.fail('Failed due to %d' % int(resp_new['status'])) + + def test_global_group_create_again(self): + utils.create_global_group(self.global_group, str(self.auth_token)) + resp_new, content_new = utils.create_global_group(self.global_group, + str(self.auth_token)) + if int(resp_new['status']) == 500: + self.fail('Identity fault') + elif int(resp_new['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(409, int(resp_new['status'])) + + def test_global_group_create_again_xml(self): + utils.create_global_group_xml(self.global_group, str(self.auth_token)) + resp_new, content_new = utils.create_global_group_xml(\ + self.global_group, + str(self.auth_token)) + content_new = etree.fromstring(content_new) + if int(resp_new['status']) == 500: + self.fail('Identity fault') + elif int(resp_new['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(409, int(resp_new['status'])) + + def test_global_group_create_unauthorized_token(self): + header = httplib2.Http(".cache") + resp, content = utils.create_global_group(\ + self.global_group, + str(self.token)) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(401, int(resp['status'])) + + def test_global_group_create_unauthorized_token_xml(self): + header = httplib2.Http(".cache") + resp, content = utils.create_global_group_xml(\ + self.global_group, + str(self.token)) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(401, int(resp['status'])) + + def test_global_group_create_expired_token(self): + header = httplib2.Http(".cache") + url = '%sgroups' % (utils.URL) + body = {"group": {"id": self.global_group, + "description": "A description ..."}} + resp, content = header.request(url, "POST", body=json.dumps(body), + headers={"Content-Type": "application/json", + "X-Auth-Token": \ + self.exp_auth_token}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(403, int(resp['status'])) + + def test_global_group_create_expired_token_xml(self): + header = httplib2.Http(".cache") + url = '%sgroups' % (utils.URL) + body = ' \ + A description... \ + ' % self.globaltenant + resp, content = header.request(url, "POST", body=body, + headers={"Content-Type": "application/xml", + "X-Auth-Token": self.exp_auth_token, + "ACCEPT": "application/xml"}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(403, int(resp['status'])) + + def test_global_group_create_missing_token(self): + header = httplib2.Http(".cache") + url = '%sgroups' % (utils.URL) + body = {"group": {"id": self.global_group, + "description": "A description ..."}} + resp, content = header.request(url, "POST", body=json.dumps(body), + headers={"Content-Type": "application/json"}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(401, int(resp['status'])) + + def test_global_group_create_missing_token_xml(self): + header = httplib2.Http(".cache") + url = '%sgroups' % (utils.URL) + body = ' \ + A description... \ + ' % self.global_group + resp, content = header.request(url, "POST", body=body, + headers={"Content-Type": "application/xml", + "ACCEPT": "application/xml"}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(401, int(resp['status'])) + + def test_global_group_create_disabled_token(self): + header = httplib2.Http(".cache") + url = '%sgroups' % (utils.URL) + body = '{"group": { "id": "%s", \ + "description": "A description ..." } }' % self.global_group + resp, content = header.request(url, "POST", body=body, + headers={"Content-Type": "application/json", + "X-Auth-Token": \ + self.disabled_token}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(403, int(resp['status'])) + + def test_global_group_create_disabled_token_xml(self): + header = httplib2.Http(".cache") + url = '%sgroups' % (utils.URL) + body = ' \ + A description... \ + ' % self.global_group + resp, content = header.request(url, "POST", body=body, + headers={"Content-Type": "application/xml", + "X-Auth-Token": self.disabled_token, + "ACCEPT": "application/xml"}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(403, int(resp['status'])) + + def test_global_group_create_invalid_token(self): + header = httplib2.Http(".cache") + url = '%sgroups' % (utils.URL) + body = '{"group": { "id": "%s", \ + "description": "A description ..." } }' % self.globaltenant + resp, content = header.request(url, "POST", body=body, + headers={"Content-Type": "application/json", + "X-Auth-Token": 'nonexsitingtoken'}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(404, int(resp['status'])) + + def test_global_group_create_invalid_token_xml(self): + header = httplib2.Http(".cache") + url = '%sgroups' % (utils.URL) + body = ' \ + A description... \ + ' % self.global_group + resp, content = header.request(url, "POST", body=body, + headers={"Content-Type": "application/xml", + "X-Auth-Token": 'nonexsitingtoken', + "ACCEPT": "application/xml"}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(404, int(resp['status'])) + + +class GetGlobalGroupsTest(GlobalGroupTest): + + def test_get_global_groups(self): + header = httplib2.Http(".cache") + utils.delete_global_group(self.global_group, str(self.auth_token)) + resp_new, content_new = utils.create_global_group(self.global_group, + str(self.auth_token)) + + url = '%sgroups' % (utils.URL) + resp, content = header.request(url, "GET", body='{}', + headers={"Content-Type": "application/json", + "X-Auth-Token": self.auth_token}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(200, int(resp['status'])) + + def test_get_global_groups_xml(self): + header = httplib2.Http(".cache") + utils.create_global_group_xml(self.global_group, str(self.auth_token)) + url = '%sgroups' % (utils.URL) + resp, content = header.request(url, "GET", body='', + headers={"Content-Type": "application/xml", + "X-Auth-Token": self.auth_token, + "ACCEPT": "application/xml"}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(200, int(resp['status'])) + + def test_get_global_groups_unauthorized_token(self): + header = httplib2.Http(".cache") + resp_new, content_new = utils.create_global_group(self.global_group, + str(self.auth_token)) + url = '%sgroups' % (utils.URL) + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body='{}', + headers={"Content-Type": "application/json", + "X-Auth-Token": self.token}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(401, int(resp['status'])) + + def test_get_global_groups_unauthorized_token_xml(self): + header = httplib2.Http(".cache") + resp_new, content_new = utils.create_global_group_xml(\ + self.global_group, + str(self.auth_token)) + url = '%sgroups' % (utils.URL) + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body='', + headers={"Content-Type": "application/xml", + "X-Auth-Token": self.token, + "ACCEPT": "application/xml"}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(401, int(resp['status'])) + + def test_get_global_groups_exp_token(self): + header = httplib2.Http(".cache") + resp_new, content_new = utils.create_global_group(self.global_group, + str(self.auth_token)) + url = '%sgroups' % (utils.URL) + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body='{}', + headers={"Content-Type": "application/json", + "X-Auth-Token": \ + self.exp_auth_token}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(403, int(resp['status'])) + + def test_get_global_groups_exp_token_xml(self): + header = httplib2.Http(".cache") + resp_new, content_new = utils.create_global_group_xml(\ + self.global_group, + str(self.auth_token)) + url = '%sgroups' % (utils.URL) + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body='', + headers={"Content-Type": "application/xml", + "X-Auth-Token": self.exp_auth_token, + "ACCEPT": "application/xml"}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(403, int(resp['status'])) + + +class GetGlobalGroupTest(GlobalGroupTest): + + def test_get_global_group(self): + header = httplib2.Http(".cache") + resp_new, content_new = utils.create_global_group(self.global_group, + str(self.auth_token)) + url = '%sgroups/%s' % (utils.URL, self.global_group) + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body='{}', + headers={"Content-Type": "application/json", + "X-Auth-Token": self.auth_token}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(200, int(resp['status'])) + + def test_get_global_group_xml(self): + header = httplib2.Http(".cache") + resp_new, content_new = utils.create_global_group_xml(\ + self.global_group, + str(self.auth_token)) + url = '%sgroups/%s' % (utils.URL, self.global_group) + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body='', + headers={"Content-Type": "application/xml", + "X-Auth-Token": self.auth_token, + "ACCEPT": "application/xml"}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(200, int(resp['status'])) + + def test_get_global_group_bad(self): + header = httplib2.Http(".cache") + resp_new, content_new = utils.create_global_group(self.global_group, + str(self.auth_token)) + url = '%sgroups/%s' % (utils.URL, 'global_group_bad') + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body='', + headers={"Content-Type": "application/json", + "X-Auth-Token": self.auth_token}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(404, int(resp['status'])) + + def test_get_global_group_bad_xml(self): + header = httplib2.Http(".cache") + resp_new, content_new = utils.create_global_group_xml(\ + self.global_group, + str(self.auth_token)) + url = '%sgroups/%s' % (utils.URL, 'global_group_bad') + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body='', + headers={"Content-Type": "application/xml", + "X-Auth-Token": self.auth_token, + "ACCEPT": "application/xml"}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(404, int(resp['status'])) + + +class UpdateGlobalGroupsTest(GlobalGroupTest): + + def test_update_global_group(self): + header = httplib2.Http(".cache") + resp_new, content_new = utils.create_global_group(self.global_group, + str(self.auth_token)) + url = '%sgroups/%s' % (utils.URL, self.global_group) + resp, content = header.request(url, "PUT", body='{"group":{\ + "id" : "%s","description" :\ + "A New description of the group..."}}' % self.global_group, + headers={"Content-Type": "application/json", + "X-Auth-Token": self.auth_token}) + body = json.loads(content) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(200, int(resp['status'])) + self.assertEqual(self.global_group, body['group']['id']) + self.assertEqual('A New description of the group...', + str(body['group']['description'])) + + def test_update_global_group_xml(self): + header = httplib2.Http(".cache") + resp_new, content_new = utils.create_global_group(self.global_group, + str(self.auth_token)) + + url = '%sgroups/%s' % (utils.URL, self.global_group) + data = u' \ + A NEW description... \ + ' % (self.global_group) + #test for Content-Type = application/json + resp, content = header.request(url, "PUT", body=data, + headers={"Content-Type": "application/xml", + "X-Auth-Token": self.auth_token, + "ACCEPT": "application/xml"}) + + body = etree.fromstring(content) + desc = body.find("{http://docs.openstack.org/identity/api/v2.0}description") + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(200, int(resp['status'])) + self.assertEqual(str(self.global_group), str(body.get('id'))) + self.assertEqual('A NEW description...', desc.text) + + def test_update_global_group_bad(self): + header = httplib2.Http(".cache") + resp_new, content_new = utils.create_global_group(self.global_group, + str(self.auth_token)) + url = '%sgroups/%s' % (utils.URL, self.global_group) + data = '{"group": { "description_bad": "A NEW description...", \ + "id":"%s" }}'\ + % (self.global_group) + #test for Content-Type = application/json + resp, content = header.request(url, "PUT", body=data, + headers={"Content-Type": "application/json", + "X-Auth-Token": self.auth_token}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(400, int(resp['status'])) + + def test_update_global_group_bad_xml(self): + header = httplib2.Http(".cache") + utils.create_global_group_xml(self.global_group, str(self.auth_token)) + url = '%sgroups/%s' % (utils.URL, self.global_group) + data = ' \ + A NEW description... \ + ' % (self.global_group) + #test for Content-Type = application/json + resp, content = header.request(url, "PUT", body=data, + headers={"Content-Type": "application/xml", + "X-Auth-Token": self.auth_token, + "ACCEPT": "application/xml"}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + + self.assertEqual(400, int(resp['status'])) + + def test_update_global_group_not_found(self): + header = httplib2.Http(".cache") + utils.create_global_group(self.global_group, str(self.auth_token)) + url = '%sgroups/NonexistingID' % (utils.URL) + data = '{"group": { "description": "A NEW description...", \ + "id":"NonexistingID"}}' + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body=data, + headers={"Content-Type": "application/json", + "X-Auth-Token": self.auth_token}) + self.assertEqual(404, int(resp['status'])) + + def test_update_global_group_not_found_xml(self): + header = httplib2.Http(".cache") + utils.create_tenant_xml(self.globaltenant, str(self.auth_token)) + url = '%sgroups/NonexistingID' % (utils.URL) + data = ' \ + \ + A NEW description... \ + ' + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body=data, + headers={"Content-Type": "application/xml", + "X-Auth-Token": self.auth_token, + "ACCEPT": "application/xml"}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(404, int(resp['status'])) + + +class DeleteGlobalGroupTest(GlobalGroupTest): + + def test_delete_global_group_not_found(self): + resp, content = utils.delete_global_group("test_global_group_1", + str(self.auth_token)) + self.assertEqual(404, int(resp['status'])) + + def test_delete_global_group_not_found_xml(self): + resp, content = utils.delete_global_group_xml("test_global_group_1", + str(self.auth_token)) + self.assertEqual(404, int(resp['status'])) + + def test_delete_global_group(self): + utils.create_tenant(self.globaltenant, str(self.auth_token)) + utils.create_tenant_group('test_global_group_delete', + self.globaltenant, str(self.auth_token)) + resp_new, content_new = utils.delete_global_group(\ + 'test_global_group_delete', + str(self.auth_token)) + resp = utils.delete_tenant(self.globaltenant, str(self.auth_token)) + self.assertEqual(204, int(resp_new['status'])) + + def test_delete_global_group_xml(self): + + utils.create_tenant_xml(self.globaltenant, str(self.auth_token)) + + utils.create_tenant_group_xml('test_global_group_delete', + self.globaltenant, str(self.auth_token)) + + resp_new, content_new = utils.delete_global_group_xml(\ + 'test_global_group_delete', + str(self.auth_token)) + utils.delete_tenant_xml(self.globaltenant, str(self.auth_token)) + + self.assertEqual(204, int(resp_new['status'])) + + +class AddUserGlobalGroupTest(unittest.TestCase): + + def setUp(self): + self.tenant = utils.get_global_tenant() + self.auth_token = utils.get_auth_token() + self.user = utils.get_user() + self.userdisabled = utils.get_userdisabled() + self.exp_auth_token = utils.get_exp_auth_token() + self.disabled_token = utils.get_disabled_token() + self.global_group = 'test_global_group' + utils.create_tenant(self.tenant, str(self.auth_token)) + utils.create_user(self.tenant, self.user, self.auth_token) + utils.add_user_json(self.tenant, self.user, self.auth_token) + self.token = utils.get_token(self.user, 'secrete', self.tenant, + 'token') + + def tearDown(self): + utils.delete_user_global_group(self.global_group, self.user, + str(self.auth_token)) + + utils.delete_user(self.tenant, self.user, str(self.auth_token)) + utils.delete_user(self.tenant, self.user, self.auth_token) + utils.delete_global_group(self.global_group, self.auth_token) + + def test_add_user_global_group(self): + resp, content = utils.create_global_group(self.global_group, + str(self.auth_token)) + utils.create_user(self.tenant, self.user, str(self.auth_token)) + resp_new, content_new = utils.add_user_global_group(self.global_group, + self.user, + str(self.auth_token)) + + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + if int(resp_new['status']) not in (200, 201): + self.fail('Failed due to %d' % int(resp_new['status'])) + + def test_add_user_global_group_xml(self): + resp, content = utils.create_global_group(self.global_group, + str(self.auth_token)) + utils.create_user(self.tenant, self.user, str(self.auth_token)) + resp_new, content_new = utils.add_user_global_group_xml(\ + self.global_group, + self.user, + str(self.auth_token)) + + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + if int(resp_new['status']) not in (200, 201): + self.fail('Failed due to %d' % int(resp_new['status'])) + + def test_add_user_global_group_conflict(self): + resp, content = utils.create_global_group(self.global_group, + str(self.auth_token)) + utils.create_user(self.tenant, self.user, str(self.auth_token)) + utils.add_user_global_group(self.global_group, self.user, + str(self.auth_token)) + resp_new, content_new = utils.add_user_global_group(self.global_group, + self.user, + str(self.auth_token)) + + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(409, int(resp_new['status'])) + + def test_add_user_global_group_conflict_xml(self): + resp, content = utils.create_global_group(self.global_group, + str(self.auth_token)) + utils.create_user(self.tenant, self.user, str(self.auth_token)) + utils.add_user_global_group_xml(self.global_group, self.user, + str(self.auth_token)) + resp_new, content_new = utils.add_user_global_group_xml(\ + self.global_group, + self.user, + str(self.auth_token)) + + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(409, int(resp_new['status'])) + + def test_add_user_global_group_unauthorized(self): + resp, content = utils.create_global_group(self.global_group, + str(self.auth_token)) + + utils.create_user(self.tenant, self.user, str(self.auth_token)) + + resp_new, content_new = utils.add_user_global_group(self.global_group, + self.user, + str(self.token)) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(401, int(resp_new['status'])) + + def test_add_user_global_group_unauthorized_xml(self): + resp, content = utils.create_global_group(self.global_group, + str(self.auth_token)) + utils.create_user(self.tenant, self.user, str(self.auth_token)) + resp_new, content_new = utils.add_user_global_group_xml(\ + self.global_group, + self.user, + str(self.token)) + + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(401, int(resp_new['status'])) + + def test_add_user_global_group_forbidden(self): + resp, content = utils.create_global_group(self.global_group, + str(self.auth_token)) + utils.create_user(self.tenant, self.user, str(self.auth_token)) + resp_new, content_new = utils.add_user_global_group(\ + self.global_group, + self.user, + str(self.disabled_token)) + + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(403, int(resp_new['status'])) + + def test_add_user_global_group_forbidden_xml(self): + resp, content = utils.create_global_group(self.global_group, + str(self.auth_token)) + utils.create_user(self.tenant, self.user, str(self.auth_token)) + resp_new, content_new = utils.add_user_global_group_xml(\ + self.global_group, + self.user, + str(self.disabled_token)) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(403, int(resp_new['status'])) + + +class GetUsersTenantGroupTest(unittest.TestCase): + + def setUp(self): + self.tenant = utils.get_global_tenant() + self.user = utils.get_user() + self.userdisabled = utils.get_userdisabled() + self.auth_token = utils.get_auth_token() + self.exp_auth_token = utils.get_exp_auth_token() + self.disabled_token = utils.get_disabled_token() + self.global_group = 'test_global_group' + utils.create_tenant(self.tenant, str(self.auth_token)) + utils.create_user(self.tenant, self.user, self.auth_token) + utils.add_user_json(self.tenant, self.user, self.auth_token) + self.token = utils.get_token(self.user, 'secrete', self.tenant, + 'token') + + def tearDown(self): + utils.delete_user_global_group(self.global_group, self.user, + str(self.auth_token)) + utils.delete_user(self.tenant, self.user, str(self.auth_token)) + utils.delete_global_group(self.global_group, self.auth_token) + + def test_get_users_global_group(self): + resp, content = utils.create_global_group(self.global_group, + str(self.auth_token)) + utils.create_user(self.tenant, self.user, str(self.auth_token)) + utils.add_user_global_group(self.global_group, self.user, + str(self.auth_token)) + resp_new, content_new = utils.get_user_global_group(\ + self.global_group, + str(self.auth_token)) + + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(200, int(resp_new['status'])) + + def test_get_users_global_group_xml(self): + resp, content = utils.create_global_group(self.global_group, + str(self.auth_token)) + utils.create_user(self.tenant, self.user, str(self.auth_token)) + utils.add_user_global_group_xml(self.global_group, self.user, + str(self.auth_token)) + resp_new, content_new = utils.get_user_global_group_xml(\ + self.global_group, + str(self.auth_token)) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(200, int(resp_new['status'])) + + def test_get_users_global_group_unauthorized(self): + resp, content = utils.create_global_group(self.global_group, + str(self.auth_token)) + utils.create_user(self.tenant, self.user, str(self.auth_token)) + utils.add_user_global_group(self.global_group, self.user, + str(self.auth_token)) + + resp_new, content_new = utils.get_user_global_group(\ + self.global_group, + str(self.token)) + + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(401, int(resp_new['status'])) + + def test_get_users_global_group_unauthorized_xml(self): + resp, content = utils.create_global_group(self.global_group, + str(self.auth_token)) + utils.create_user(self.tenant, self.user, str(self.auth_token)) + utils.add_user_global_group(self.global_group, self.user, + str(self.auth_token)) + resp_new, content_new = utils.get_user_global_group_xml(\ + self.global_group, + str(self.token)) + + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(401, int(resp_new['status'])) + + def test_get_users_global_group_forbidden(self): + resp, content = utils.create_global_group(self.global_group, + str(self.auth_token)) + utils.create_user(self.tenant, self.user, str(self.auth_token)) + utils.add_user_global_group(self.global_group, self.user, + str(self.auth_token)) + resp_new, content_new = utils.get_user_global_group(\ + self.global_group, + str(self.disabled_token)) + + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(403, int(resp_new['status'])) + + def test_get_users_global_group_forbidden_xml(self): + resp, content = utils.create_global_group(self.global_group, + str(self.auth_token)) + utils.create_user(self.tenant, self.user, str(self.auth_token)) + utils.add_user_global_group(self.global_group, self.user, + str(self.auth_token)) + resp_new, content_new = utils.get_user_global_group_xml(\ + self.global_group, + str(self.disabled_token)) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(403, int(resp_new['status'])) + + def test_get_users_global_group_expired(self): + resp, content = utils.create_global_group(self.global_group, + str(self.auth_token)) + utils.create_user(self.tenant, self.user, str(self.auth_token)) + utils.add_user_global_group(self.global_group, self.user, + str(self.auth_token)) + resp_new, content_new = utils.get_user_global_group(\ + self.global_group, + str(self.exp_auth_token)) + + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(403, int(resp_new['status'])) + + def test_get_users_global_group_expired_xml(self): + resp, content = utils.create_global_group(self.global_group, + str(self.auth_token)) + utils.create_user(self.tenant, self.user, str(self.auth_token)) + utils.add_user_global_group(self.global_group, self.user, + str(self.auth_token)) + resp_new, content_new = utils.get_user_global_group_xml(\ + self.global_group, + str(self.exp_auth_token)) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(403, int(resp_new['status'])) + + +class DeleteUsersGlobalGroupTest(unittest.TestCase): + + def setUp(self): + self.tenant = utils.get_global_tenant() + self.user = utils.get_user() + self.userdisabled = utils.get_userdisabled() + self.auth_token = utils.get_auth_token() + self.exp_auth_token = utils.get_exp_auth_token() + self.disabled_token = utils.get_disabled_token() + self.global_group = 'test_global_group' + utils.create_tenant(self.tenant, str(self.auth_token)) + utils.create_user(self.tenant, self.user, self.auth_token) + utils.add_user_json(self.tenant, self.user, self.auth_token) + self.token = utils.get_token(self.user, 'secrete', self.tenant, + 'token') + + def tearDown(self): + utils.delete_user_global_group(self.global_group, self.user, + str(self.auth_token)) + + utils.delete_user(self.tenant, self.user, str(self.auth_token)) + utils.delete_global_group(self.global_group, self.auth_token) + + def test_delete_user_global_group(self): + resp, content = utils.create_global_group(self.global_group, + str(self.auth_token)) + utils.create_user(self.tenant, self.user, str(self.auth_token)) + utils.add_user_global_group(self.global_group, self.user, + str(self.auth_token)) + + resp_new, content_new = utils.delete_user_global_group(\ + self.global_group, + self.user, + str(self.auth_token)) + + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(204, int(resp_new['status'])) + + def test_delete_user_global_group_xml(self): + resp, content = utils.create_global_group(self.global_group, + str(self.auth_token)) + utils.create_user(self.tenant, self.user, str(self.auth_token)) + utils.add_user_global_group(self.global_group, self.user, + str(self.auth_token)) + resp_new, content_new = utils.delete_user_global_group_xml(\ + self.global_group, + self.user, + str(self.auth_token)) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(204, int(resp_new['status'])) + + def test_delete_user_global_group_notfound(self): + resp, content = utils.create_global_group(self.global_group, + str(self.auth_token)) + utils.create_user(self.tenant, self.user, str(self.auth_token)) + utils.add_user_global_group(self.global_group, self.user, + str(self.disabled_token)) + utils.delete_user_global_group(self.global_group, self.user, + str(self.auth_token)) + resp_new, content_new = utils.delete_user_global_group( + self.global_group, + self.user, + str(self.auth_token)) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(404, int(resp_new['status'])) + + def test_delete_user_global_group_notfound_xml(self): + resp, content = utils.create_global_group(self.global_group, + str(self.auth_token)) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + utils.create_user(self.tenant, self.user, str(self.auth_token)) + utils.add_user_global_group(self.global_group, self.user, + str(self.disabled_token)) + utils.delete_user_global_group(self.global_group, self.user, + str(self.auth_token)) + resp_new, content_new = utils.delete_user_global_group_xml(\ + self.global_group, self.user, + str(self.auth_token)) + self.assertEqual(404, int(resp_new['status'])) + +if __name__ == '__main__': + unittest.main() diff --git a/keystone/test/unit/test_keystone.py b/keystone/test/unit/test_keystone.py new file mode 100644 index 00000000..3b17d9b2 --- /dev/null +++ b/keystone/test/unit/test_keystone.py @@ -0,0 +1,60 @@ +import logging +from lxml import etree +import os +import unittest + +MODULE_EXTENSIONS = set('.py'.split()) +TEST_FILES = ['test_authentication.py', 'test_keystone.py', 'test_tenants.py', + 'test_common.py', 'test_users.py', 'test_tenant_groups.py', + 'test_token.py', 'test_version.py', 'test_groups.py'] + + +def unit_test_extractor(tup, path, filenames): + """Pull ``unittest.TestSuite``s from modules in path + if the path represents a valid Python package. Accumulate + results in `tup[1]`. + """ + package_path, suites = tup + logging.debug('Path: %s', path) + logging.debug('Filenames: %s', filenames) + relpath = os.path.relpath(path, package_path) + relpath_pieces = relpath.split(os.sep) + + if relpath_pieces[0] == '.': # Base directory. + relpath_pieces.pop(0) # Otherwise, screws up module name. + elif not any(os.path.exists(os.path.join(path, '__init__' + ext)) + for ext in MODULE_EXTENSIONS): + return # Not a package directory and not the base directory, reject. + + logging.info('Base: %s', '.'.join(relpath_pieces)) + for filename in filenames: + if filename not in TEST_FILES: + continue + base, ext = os.path.splitext(filename) + #if ext not in MODULE_EXTENSIONS : # Not a Python module. + # continue + logging.info('Module: %s', base) + module_name = '.'.join(relpath_pieces + [base]) + logging.info('Importing from %s', module_name) + module = __import__(module_name) + module_suites = unittest.defaultTestLoader.loadTestsFromModule(module) + logging.info('Got suites: %s', module_suites) + suites += module_suites + + +def get_test_suites(path): + """:return: Iterable of suites for the packages/modules + present under :param:`path`. + """ + logging.info('Base path: %s', package_path) + suites = [] + os.path.walk(package_path, unit_test_extractor, (package_path, suites)) + logging.info('Got suites: %s', suites) + return suites + +if __name__ == '__main__': + logging.basicConfig(level=logging.WARN) + package_path = os.path.dirname(os.path.abspath(__file__)) + suites = get_test_suites(package_path) + for suite in suites: + unittest.TextTestRunner(verbosity=1).run(suite) diff --git a/keystone/test/unit/test_roles.py b/keystone/test/unit/test_roles.py new file mode 100644 index 00000000..10b16d27 --- /dev/null +++ b/keystone/test/unit/test_roles.py @@ -0,0 +1,682 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 +# Copyright (c) 2010-2011 OpenStack, LLC. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +import httplib2 +import json +from lxml import etree +import os +import sys +sys.path.append(os.path.abspath(os.path.join(os.path.abspath(__file__), + '..', '..', '..', '..', 'keystone'))) +import unittest + +import test_common as utils +from test_common import URL + +class RolesTest(unittest.TestCase): + def setUp(self): + self.tenant = utils.get_tenant() + self.password = utils.get_password() + self.email = utils.get_email() + self.user = utils.get_user() + self.userdisabled = utils.get_userdisabled() + self.auth_token = utils.get_auth_token() + self.exp_auth_token = utils.get_exp_auth_token() + self.disabled_token = utils.get_disabled_token() + self.missing_token = utils.get_none_token() + self.invalid_token = utils.get_non_existing_token() + utils.create_tenant(self.tenant, str(self.auth_token)) + utils.create_user(self.tenant, self.user, self.auth_token) + self.token = utils.get_token(self.user, 'secrete', self.tenant, + 'token') + + def tearDown(self): + utils.delete_user(self.tenant, self.user, self.auth_token) + utils.delete_tenant(self.tenant, self.auth_token) + +class GetRolesTest(RolesTest): + def test_get_roles(self): + header = httplib2.Http(".cache") + url = '%sroles' % (utils.URL) + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body='{}', + headers={"Content-Type": "application/json", + "X-Auth-Token": self.auth_token}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(200, int(resp['status'])) + + #verify content + obj = json.loads(content) + if not "roles" in obj: + raise self.fail("Expecting Roles") + roles = obj["roles"]["values"] + if len(roles) != 1: + self.fail("Roles not of required length.") + + role = roles[0] + if not "id" in role: + role_id = None + else: + role_id = role["id"] + if role_id != 'Admin': + self.fail("Not the expected Role") + + + def test_get_roles_xml(self): + header = httplib2.Http(".cache") + url = '%sroles' % (utils.URL) + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body='', + headers={"Content-Type": "application/xml", + "X-Auth-Token": self.auth_token, + "ACCEPT": "application/xml"}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(200, int(resp['status'])) + + # Validate Returned Content + dom = etree.Element("root") + dom.append(etree.fromstring(content)) + roles = dom.find("{http://docs.openstack.org/identity/api/v2.0}" \ + "roles") + if roles == None: + self.fail("Expecting Roles") + roles = roles.findall("{http://docs.openstack.org/identity/api/v2.0}" \ + "role") + if len(roles) != 1: + self.fail("Not the expected Role count") + for role in roles: + if role.get("id") != 'Admin': + self.fail("Not the expected Role") + + + def test_get_roles_exp_token(self): + header = httplib2.Http(".cache") + url = '%sroles' % (utils.URL) + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body='{}', + headers={"Content-Type": "application/json", + "X-Auth-Token": self.exp_auth_token}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(403, int(resp['status'])) + + def test_get_roles_exp_token_xml(self): + header = httplib2.Http(".cache") + url = '%stenants' % (utils.URL) + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body='', + headers={"Content-Type": "application/xml", + "X-Auth-Token": self.exp_auth_token, + "ACCEPT": "application/xml"}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(403, int(resp['status'])) + +class GetRoleTest(RolesTest): + + def test_get_role(self): + self.role = 'Admin' + header = httplib2.Http(".cache") + url = '%sroles/%s' % (utils.URL, self.role) + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body='{}', + headers={"Content-Type": "application/json", + "X-Auth-Token": self.auth_token}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(200, int(resp['status'])) + + #verify content + obj = json.loads(content) + if not "role" in obj: + raise fault.BadRequestFault("Expecting Role") + role = obj["role"] + if not "id" in role: + role_id = None + else: + role_id = role["id"] + if role_id != 'Admin': + self.fail("Not the expected Role") + + def test_get_role_xml(self): + self.role = 'Admin' + header = httplib2.Http(".cache") + url = '%sroles/%s' % (utils.URL, self.role) + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body='', + headers={"Content-Type": "application/xml", + "X-Auth-Token": self.auth_token, + "ACCEPT": "application/xml"}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(200, int(resp['status'])) + + #verify content + dom = etree.Element("root") + dom.append(etree.fromstring(content)) + role = dom.find("{http://docs.openstack.org/identity/api/v2.0}" \ + "role") + if role == None: + self.fail("Expecting Role") + role_id = role.get("id") + if role_id != 'Admin': + self.fail("Not the expected Role") + + def test_get_role_bad(self): + header = httplib2.Http(".cache") + url = '%sroles/%s' % (utils.URL, 'tenant_bad') + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body='', + headers={"Content-Type": "application/json", + "X-Auth-Token": self.auth_token}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(404, int(resp['status'])) + + def test_get_role_xml_bad(self): + header = httplib2.Http(".cache") + url = '%sroles/%s' % (utils.URL, 'tenant_bad') + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body='', + headers={"Content-Type": "application/json", + "X-Auth-Token": self.auth_token}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(404, int(resp['status'])) + + def test_get_role_expired_token(self): + self.role = 'Admin' + header = httplib2.Http(".cache") + url = '%sroles/%s' % (utils.URL, self.role) + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body='{}', + headers={"Content-Type": "application/json", + "X-Auth-Token": self.exp_auth_token}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(403, int(resp['status'])) + + def test_get_role_xml_using_expired_token(self): + self.role = 'Admin' + header = httplib2.Http(".cache") + url = '%sroles/%s' % (utils.URL, self.role) + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body='', + headers={"Content-Type": "application/xml", + "X-Auth-Token": self.exp_auth_token, + "ACCEPT": "application/xml"}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(403, int(resp['status'])) + + def test_get_role_using_disabled_token(self): + self.role = 'Admin' + header = httplib2.Http(".cache") + url = '%sroles/%s' % (utils.URL, self.role) + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body='{}', + headers={"Content-Type": "application/json", + "X-Auth-Token": self.disabled_token}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(403, int(resp['status'])) + + def test_get_role_xml_using_disabled_token(self): + self.role = 'Admin' + header = httplib2.Http(".cache") + url = '%sroles/%s' % (utils.URL, self.role) + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body='', + headers={"Content-Type": "application/xml", + "X-Auth-Token": self.disabled_token, + "ACCEPT": "application/xml"}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(403, int(resp['status'])) + + def test_get_role_using_missing_token(self): + self.role = 'Admin' + header = httplib2.Http(".cache") + url = '%sroles/%s' % (utils.URL, self.role) + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body='{}', + headers={"Content-Type": "application/json", + "X-Auth-Token": self.missing_token}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(401, int(resp['status'])) + + def test_get_role_xml_using_missing_token(self): + self.role = 'Admin' + header = httplib2.Http(".cache") + url = '%sroles/%s' % (utils.URL, self.role) + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body='', + headers={"Content-Type": "application/xml", + "X-Auth-Token": self.missing_token, + "ACCEPT": "application/xml"}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(401, int(resp['status'])) + + def test_get_role_using_invalid_token(self): + self.role = 'Admin' + header = httplib2.Http(".cache") + url = '%sroles/%s' % (utils.URL, self.role) + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body='{}', + headers={"Content-Type": "application/json", + "X-Auth-Token": self.invalid_token}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(404, int(resp['status'])) + + def test_get_role_xml_using_invalid_token(self): + self.role = 'Admin' + header = httplib2.Http(".cache") + url = '%sroles/%s' % (utils.URL, self.role) + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body='', + headers={"Content-Type": "application/xml", + "X-Auth-Token": self.invalid_token, + "ACCEPT": "application/xml"}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(404, int(resp['status'])) + + +class CreateRoleRefTest(RolesTest): + def test_role_ref_create_json(self): + utils.add_user_json(self.tenant, self.user, self.auth_token) + resp, content = utils.create_role_ref(self.user, 'Admin', self.tenant, + str(self.auth_token)) + resp_val = int(resp['status']) + self.assertEqual(201, resp_val) + + def test_role_ref_create_xml(self): + utils.add_user_json(self.tenant, self.user, self.auth_token) + resp, content = utils.create_role_ref_xml(self.user, 'Admin', self.tenant, + str(self.auth_token)) + resp_val = int(resp['status']) + self.assertEqual(201, resp_val) + + def test_role_ref_create_json_using_expired_token(self): + utils.add_user_json(self.tenant, self.user, self.auth_token) + resp, content = utils.create_role_ref(self.user, 'Admin', self.tenant, + str(self.exp_auth_token)) + resp_val = int(resp['status']) + self.assertEqual(403, resp_val) + + def test_role_ref_create_json_using_disabled_token(self): + utils.add_user_json(self.tenant, self.user, self.auth_token) + resp, content = utils.create_role_ref(self.user, 'Admin', self.tenant, + str(self.disabled_token)) + resp_val = int(resp['status']) + self.assertEqual(403, resp_val) + + def test_role_ref_create_json_using_missing_token(self): + utils.add_user_json(self.tenant, self.user, self.auth_token) + resp, content = utils.create_role_ref(self.user, 'Admin', self.tenant, + str(self.missing_token)) + resp_val = int(resp['status']) + self.assertEqual(401, resp_val) + + def test_role_ref_create_json_using_invalid_token(self): + utils.add_user_json(self.tenant, self.user, self.auth_token) + resp, content = utils.create_role_ref(self.user, 'Admin', self.tenant, + str(self.invalid_token)) + resp_val = int(resp['status']) + self.assertEqual(404, resp_val) + + +class GetRoleRefsTest(RolesTest): + def test_get_rolerefs(self): + header = httplib2.Http(".cache") + utils.add_user_json(self.tenant, self.user, self.auth_token) + resp, content = utils.create_role_ref(self.user, 'Admin', self.tenant, + str(self.auth_token)) + url = '%susers/%s/roleRefs' % (URL, self.user) + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body='{}', + headers={"Content-Type": "application/json", + "X-Auth-Token": str(self.auth_token)}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(200, int(resp['status'])) + + #verify content + obj = json.loads(content) + if not "roleRefs" in obj: + raise self.fail("Expecting RoleRefs") + + def test_get_rolerefs_xml(self): + header = httplib2.Http(".cache") + utils.add_user_json(self.tenant, self.user, self.auth_token) + resp, content = utils.create_role_ref(self.user, 'Admin', self.tenant, + str(self.auth_token)) + url = '%susers/%s/roleRefs' % (URL, self.user) + #test for Content-Type = application/xml + resp, content = header.request(url, "GET", body='{}', + headers={"Content-Type": "application/xml", + "X-Auth-Token": str(self.auth_token), + "ACCEPT": "application/xml"}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(200, int(resp['status'])) + #verify content + dom = etree.Element("root") + dom.append(etree.fromstring(content)) + roles = dom.find("{http://docs.openstack.org/identity/api/v2.0}" \ + "roleRefs") + if roles == None: + self.fail("Expecting Role Refs") + + def test_get_rolerefs_using_expired_token(self): + header = httplib2.Http(".cache") + utils.add_user_json(self.tenant, self.user, self.auth_token) + resp, content = utils.create_role_ref(self.user, 'Admin', self.tenant, + str(self.auth_token)) + url = '%susers/%s/roleRefs' % (URL, self.user) + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body='{}', + headers={"Content-Type": "application/json", + "X-Auth-Token": str(self.exp_auth_token)}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(403, int(resp['status'])) + + def test_get_rolerefs_xml_using_expired_token(self): + header = httplib2.Http(".cache") + utils.add_user_json(self.tenant, self.user, self.auth_token) + resp, content = utils.create_role_ref(self.user, 'Admin', self.tenant, + str(self.auth_token)) + url = '%susers/%s/roleRefs' % (URL, self.user) + #test for Content-Type = application/xml + resp, content = header.request(url, "GET", body='{}', + headers={"Content-Type": "application/xml", + "X-Auth-Token": str(self.exp_auth_token), + "ACCEPT": "application/xml"}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(403, int(resp['status'])) + + def test_get_rolerefs_using_disabled_token(self): + header = httplib2.Http(".cache") + utils.add_user_json(self.tenant, self.user, self.auth_token) + resp, content = utils.create_role_ref(self.user, 'Admin', self.tenant, + str(self.auth_token)) + url = '%susers/%s/roleRefs' % (URL, self.user) + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body='{}', + headers={"Content-Type": "application/json", + "X-Auth-Token": str(self.disabled_token)}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(403, int(resp['status'])) + + def test_get_rolerefs_xml_using_disabled_token(self): + header = httplib2.Http(".cache") + utils.add_user_json(self.tenant, self.user, self.auth_token) + resp, content = utils.create_role_ref(self.user, 'Admin', self.tenant, + str(self.auth_token)) + url = '%susers/%s/roleRefs' % (URL, self.user) + #test for Content-Type = application/xml + resp, content = header.request(url, "GET", body='{}', + headers={"Content-Type": "application/xml", + "X-Auth-Token": str(self.disabled_token), + "ACCEPT": "application/xml"}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(403, int(resp['status'])) + + def test_get_rolerefs_using_missing_token(self): + header = httplib2.Http(".cache") + utils.add_user_json(self.tenant, self.user, self.auth_token) + resp, content = utils.create_role_ref(self.user, 'Admin', self.tenant, + str(self.auth_token)) + url = '%susers/%s/roleRefs' % (URL, self.user) + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body='{}', + headers={"Content-Type": "application/json", + "X-Auth-Token": str(self.missing_token)}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(401, int(resp['status'])) + + def test_get_rolerefs_xml_using_missing_token(self): + header = httplib2.Http(".cache") + utils.add_user_json(self.tenant, self.user, self.auth_token) + resp, content = utils.create_role_ref(self.user, 'Admin', self.tenant, + str(self.auth_token)) + url = '%susers/%s/roleRefs' % (URL, self.user) + #test for Content-Type = application/xml + resp, content = header.request(url, "GET", body='{}', + headers={"Content-Type": "application/xml", + "X-Auth-Token": str(self.missing_token), + "ACCEPT": "application/xml"}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(401, int(resp['status'])) + + def test_get_rolerefs_using_invalid_token(self): + header = httplib2.Http(".cache") + utils.add_user_json(self.tenant, self.user, self.auth_token) + resp, content = utils.create_role_ref(self.user, 'Admin', self.tenant, + str(self.auth_token)) + url = '%susers/%s/roleRefs' % (URL, self.user) + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body='{}', + headers={"Content-Type": "application/json", + "X-Auth-Token": str(self.invalid_token)}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(404, int(resp['status'])) + + def test_get_rolerefs_xml_using_missing_token(self): + header = httplib2.Http(".cache") + utils.add_user_json(self.tenant, self.user, self.auth_token) + resp, content = utils.create_role_ref(self.user, 'Admin', self.tenant, + str(self.auth_token)) + url = '%susers/%s/roleRefs' % (URL, self.user) + #test for Content-Type = application/xml + resp, content = header.request(url, "GET", body='{}', + headers={"Content-Type": "application/xml", + "X-Auth-Token": str(self.invalid_token), + "ACCEPT": "application/xml"}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(404, int(resp['status'])) + + +class DeleteRoleRefTest(RolesTest): + def test_delete_roleref(self): + header = httplib2.Http(".cache") + utils.add_user_json(self.tenant, self.user, self.auth_token) + resp, content = utils.create_role_ref(self.user, 'Admin', self.tenant, + str(self.auth_token)) + resp_val = int(resp['status']) + self.assertEqual(201, resp_val) + obj = json.loads(content) + if not "roleRef" in obj: + raise fault.BadRequestFault("Expecting RoleRef") + roleRef = obj["roleRef"] + if not "id" in roleRef: + role_ref_id = None + else: + role_ref_id = roleRef["id"] + if role_ref_id is None: + raise fault.BadRequestFault("Expecting RoleRefId") + url = '%susers/%s/roleRefs/%s' % (URL, self.user, role_ref_id) + resp, content = header.request(url, "DELETE", body='', + headers={"Content-Type": "application/json", + "X-Auth-Token": str(self.auth_token)}) + resp_val = int(resp['status']) + self.assertEqual(204, resp_val) + + def test_delete_roleref_using_expired_token(self): + header = httplib2.Http(".cache") + utils.add_user_json(self.tenant, self.user, self.auth_token) + resp, content = utils.create_role_ref(self.user, 'Admin', self.tenant, + str(self.auth_token)) + resp_val = int(resp['status']) + self.assertEqual(201, resp_val) + obj = json.loads(content) + if not "roleRef" in obj: + raise fault.BadRequestFault("Expecting RoleRef") + roleRef = obj["roleRef"] + if not "id" in roleRef: + role_ref_id = None + else: + role_ref_id = roleRef["id"] + if role_ref_id is None: + raise fault.BadRequestFault("Expecting RoleRefId") + url = '%susers/%s/roleRefs/%s' % (URL, self.user, role_ref_id) + resp, content = header.request(url, "DELETE", body='', + headers={"Content-Type": "application/json", + "X-Auth-Token": str(self.exp_auth_token)}) + resp_val = int(resp['status']) + self.assertEqual(403, resp_val) + + def test_delete_roleref_using_disabled_token(self): + header = httplib2.Http(".cache") + utils.add_user_json(self.tenant, self.user, self.auth_token) + resp, content = utils.create_role_ref(self.user, 'Admin', self.tenant, + str(self.auth_token)) + resp_val = int(resp['status']) + self.assertEqual(201, resp_val) + obj = json.loads(content) + if not "roleRef" in obj: + raise fault.BadRequestFault("Expecting RoleRef") + roleRef = obj["roleRef"] + if not "id" in roleRef: + role_ref_id = None + else: + role_ref_id = roleRef["id"] + if role_ref_id is None: + raise fault.BadRequestFault("Expecting RoleRefId") + url = '%susers/%s/roleRefs/%s' % (URL, self.user, role_ref_id) + resp, content = header.request(url, "DELETE", body='', + headers={"Content-Type": "application/json", + "X-Auth-Token": str(self.disabled_token)}) + resp_val = int(resp['status']) + self.assertEqual(403, resp_val) + + def test_delete_roleref_using_missing_token(self): + header = httplib2.Http(".cache") + utils.add_user_json(self.tenant, self.user, self.auth_token) + resp, content = utils.create_role_ref(self.user, 'Admin', self.tenant, + str(self.auth_token)) + resp_val = int(resp['status']) + self.assertEqual(201, resp_val) + obj = json.loads(content) + if not "roleRef" in obj: + raise fault.BadRequestFault("Expecting RoleRef") + roleRef = obj["roleRef"] + if not "id" in roleRef: + role_ref_id = None + else: + role_ref_id = roleRef["id"] + if role_ref_id is None: + raise fault.BadRequestFault("Expecting RoleRefId") + url = '%susers/%s/roleRefs/%s' % (URL, self.user, role_ref_id) + resp, content = header.request(url, "DELETE", body='', + headers={"Content-Type": "application/json", + "X-Auth-Token": str(self.missing_token)}) + resp_val = int(resp['status']) + self.assertEqual(401, resp_val) + + def test_delete_roleref_using_invalid_token(self): + header = httplib2.Http(".cache") + utils.add_user_json(self.tenant, self.user, self.auth_token) + resp, content = utils.create_role_ref(self.user, 'Admin', self.tenant, + str(self.auth_token)) + resp_val = int(resp['status']) + self.assertEqual(201, resp_val) + obj = json.loads(content) + if not "roleRef" in obj: + raise fault.BadRequestFault("Expecting RoleRef") + roleRef = obj["roleRef"] + if not "id" in roleRef: + role_ref_id = None + else: + role_ref_id = roleRef["id"] + if role_ref_id is None: + raise fault.BadRequestFault("Expecting RoleRefId") + url = '%susers/%s/roleRefs/%s' % (URL, self.user, role_ref_id) + resp, content = header.request(url, "DELETE", body='', + headers={"Content-Type": "application/json", + "X-Auth-Token": str(self.invalid_token)}) + resp_val = int(resp['status']) + self.assertEqual(404, resp_val) + + +if __name__ == '__main__': + unittest.main() diff --git a/keystone/test/unit/test_server.py b/keystone/test/unit/test_server.py new file mode 100644 index 00000000..294b1e54 --- /dev/null +++ b/keystone/test/unit/test_server.py @@ -0,0 +1,86 @@ +import unittest +import os +import sys +import json + +sys.path.append(os.path.abspath(os.path.join(os.path.abspath(__file__), + '..', '..', '..', '..', 'keystone'))) + +from keystone import server +import keystone.logic.types.auth as auth +import keystone.logic.types.fault as fault + +from StringIO import StringIO +from datetime import date +from lxml import etree +from webob import Request +from webob import Response + +class TestServer(unittest.TestCase): + '''Unit tests for server.py.''' + + request = None + auth_data = None + + def setUp(self): + environ = {'wsgi.url_scheme': 'http'} + self.request = Request(environ) + self.auth_data = auth.AuthData(auth.Token(date.today(),"2231312"), auth.User("username","12345",auth.Groups([],[]))) + + #def tearDown(self): + + def test_is_xml_response(self): + self.assertFalse(server.is_xml_response(self.request)) + self.request.headers["Accept"] = "application/xml" + self.request.content_type="application/json" + self.assertTrue(server.is_xml_response(self.request)) + + def test_send_result_xml(self): + self.request.headers["Accept"] = "application/xml" + response = server.send_result(200,self.request,self.auth_data); + + self.assertTrue(response.headers['content-type'] == "application/xml; charset=UTF-8") + xml = etree.fromstring(response.unicode_body) + + user = xml.find("{http://docs.openstack.org/identity/api/v2.0}user") + token = xml.find("{http://docs.openstack.org/identity/api/v2.0}token") + + self.assertTrue(user.get("username"),"username") + self.assertTrue(user.get("tenantId"),'12345'); + self.assertTrue(token.get("id"),'2231312'); + self.assertTrue(token.get("expires"),date.today()); + + def test_send_result_json(self): + self.request.headers["Accept"] = "application/json" + response = server.send_result(200,self.request,self.auth_data); + self.assertTrue(response.headers['content-type'] == "application/json; charset=UTF-8") + dict = json.loads(response.unicode_body) + self.assertTrue(dict['auth']['user']['username'],'username'); + self.assertTrue(dict['auth']['user']['tenantId'],'12345'); + self.assertTrue(dict['auth']['token']['id'],'2231312'); + self.assertTrue(dict['auth']['token']['expires'],date.today()); + + def test_get_auth_token(self): + self.request.headers["X-Auth-Token"]="Test token" + self.assertTrue(server.get_auth_token(self.request),"Test Token") + + def test_get_normalized_request_content_exception(self): + self.assertRaises(fault.IdentityFault,server.get_normalized_request_content,None,self.request) + + def test_get_normalized_request_content_xml(self): + self.request.environ["CONTENT_TYPE"]="application/xml" + pwd_cred = auth.PasswordCredentials("username","password","1") + body = ' \ + ' + str=StringIO() + str.write(body) + self.request.environ["wsgi.input"]=str + self.request.environ["CONTENT_LENGTH"] = str.len + #TODO: I THINK THIS belongs in a test for auth.py. + + +if __name__ == '__main__': + unittest.main() \ No newline at end of file diff --git a/keystone/test/unit/test_tenant_groups.py b/keystone/test/unit/test_tenant_groups.py new file mode 100644 index 00000000..21bb9221 --- /dev/null +++ b/keystone/test/unit/test_tenant_groups.py @@ -0,0 +1,1217 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 +# Copyright (c) 2010-2011 OpenStack, LLC. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +import httplib2 +import json +from lxml import etree +import os +import sys +sys.path.append(os.path.abspath(os.path.join(os.path.abspath(__file__), + '..', '..', '..', '..', 'keystone'))) +import unittest + +import test_common as util + + +class TenantGroupTest(unittest.TestCase): + + def setUp(self): + self.tenant = util.get_another_tenant() + self.user = util.get_user() + self.userdisabled = util.get_userdisabled() + self.auth_token = util.get_auth_token() + self.exp_auth_token = util.get_exp_auth_token() + self.disabled_token = util.get_disabled_token() + self.tenant_group = 'test_tenant_group_new' + util.create_tenant(self.tenant, str(self.auth_token)) + util.create_user(self.tenant, self.user, self.auth_token) + util.add_user_json(self.tenant, self.user, self.auth_token) + self.token = util.get_token(self.user, 'secrete', self.tenant, + 'token') + + def tearDown(self): + resp = util.delete_user(self.tenant, self.user, + str(self.auth_token)) + + resp, content = util.delete_tenant_group(self.tenant_group, + self.tenant, + self.auth_token) + resp = util.delete_tenant(self.tenant, self.auth_token) + + +class CreateTenantGroupTest(TenantGroupTest): + + def test_tenant_group_create(self): + util.delete_user(self.tenant, self.user, + str(self.auth_token)) + resp = util.delete_tenant(self.tenant, str(self.auth_token)) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + util.create_tenant(self.tenant, str(self.auth_token)) + resp, content = util.delete_tenant_group(self.tenant_group, + self.tenant, + str(self.auth_token)) + resp, content = util.create_tenant_group(self.tenant_group, + self.tenant, + str(self.auth_token)) + + if int(resp['status']) not in (200, 201): + self.fail('Failed due to %d' % int(resp['status'])) + + def test_tenant_group_create_xml(self): + util.delete_user(self.tenant, self.user, + str(self.auth_token)) + resp = util.delete_tenant_xml(self.tenant, + str(self.auth_token)) + resp, content = util.create_tenant_xml(self.tenant, + str(self.auth_token)) + resp, content = util.delete_tenant_group_xml(self.tenant_group, + self.tenant, + str(self.auth_token)) + resp, content = util.create_tenant_group_xml(self.tenant_group, + self.tenant, + str(self.auth_token)) + + content = etree.fromstring(content) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + if int(resp['status']) not in (200, 201): + self.fail('Failed due to %d' % int(resp['status'])) + + def test_tenant_group_create_again(self): + resp, content = util.create_tenant(self.tenant, + str(self.auth_token)) + resp, content = util.create_tenant_group(self.tenant_group, + self.tenant, + str(self.auth_token)) + resp, content = util.create_tenant_group(self.tenant_group, + self.tenant, + str(self.auth_token)) + if int(resp['status']) == 200: + self.tenant = content['tenant']['id'] + self.tenant_group = content['group']['id'] + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(409, int(resp['status'])) + + def test_tenant_group_create_again_xml(self): + resp, content = util.create_tenant_xml("test_tenant", + str(self.auth_token)) + resp, content = util.create_tenant_group_xml(self.tenant_group, + self.tenant, + str(self.auth_token)) + resp_new, content_new = util.create_tenant_group_xml(self.tenant_group, + self.tenant, + str(self.auth_token)) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(409, int(resp['status'])) + + def test_tenant_group_create_unauthorized_token(self): + header = httplib2.Http(".cache") + resp, content = util.create_tenant(self.tenant, str(self.auth_token)) + if int(resp['status']) == 200: + self.tenant = content['tenant']['id'] + resp, content = util.create_tenant_group_xml(self.tenant_group, + self.tenant, + str(self.auth_token)) + + if int(resp['status']) == 200: + self.tenant_group = resp['group']['id'] + url = '%stenants/%s/groups' % (util.URL, self.tenant) + body = {"group": {"id": self.tenant_group, + "description": "A description ..."}} + resp, content = header.request(url, "POST", body=json.dumps(body), + headers={"Content-Type": "application/json", + "X-Auth-Token": self.token}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(401, int(resp['status'])) + + def test_tenant_group_create_unauthorized_token_xml(self): + header = httplib2.Http(".cache") + resp, content = util.create_tenant(self.tenant, str(self.auth_token)) + if int(resp['status']) == 200: + self.tenant = content['tenant']['id'] + url = '%stenants/%s/groups' % (util.URL, self.tenant) + body = ' \ + A description... \ + ' % self.tenant_group + resp, content = header.request(url, "POST", body=body, + headers={"Content-Type": "application/xml", + "X-Auth-Token": self.token, + "ACCEPT": "application/xml"}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(401, int(resp['status'])) + + def test_tenant_group_create_expired_token(self): + header = httplib2.Http(".cache") + resp, content = util.create_tenant(self.tenant, str(self.auth_token)) + if int(resp['status']) == 200: + self.tenant = content['tenant']['id'] + url = '%stenants/%s/groups' % (util.URL, self.tenant) + body = {"group": {"id": self.tenant_group, + "description": "A description ..."}} + resp, content = header.request(url, "POST", body=json.dumps(body), + headers={"Content-Type": "application/json", + "X-Auth-Token": self.exp_auth_token}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(403, int(resp['status'])) + + def test_tenant_group_create_expired_token_xml(self): + header = httplib2.Http(".cache") + resp, content = util.create_tenant_xml(self.tenant, + str(self.auth_token)) + content = etree.fromstring(content) + if int(resp['status']) == 200: + self.tenant = content.get('id') + url = '%stenants/%s/groups' % (util.URL, self.tenant) + body = ' \ + \ + A description... \ + ' % self.tenant + resp, content = header.request(url, "POST", body=body, + headers={"Content-Type": "application/xml", + "X-Auth-Token": self.exp_auth_token, + "ACCEPT": "application/xml"}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(403, int(resp['status'])) + + def test_tenant_group_create_missing_token(self): + header = httplib2.Http(".cache") + resp, content = util.create_tenant(self.tenant, str(self.auth_token)) + if int(resp['status']) == 200: + self.tenant = content['tenant']['id'] + url = '%stenants/%s/groups' % (util.URL, self.tenant) + body = {"group": {"id": self.tenant_group, + "description": "A description ..."}} + resp, content = header.request(url, "POST", body=json.dumps(body), + headers={"Content-Type": "application/json"}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(401, int(resp['status'])) + + def test_tenant_group_create_missing_token_xml(self): + header = httplib2.Http(".cache") + resp, content = util.create_tenant_xml(self.tenant, + str(self.auth_token)) + content = etree.fromstring(content) + if int(resp['status']) == 200: + self.tenant = content.get('id') + url = '%stenants/%s/groups' % (util.URL, self.tenant) + body = ' \ + \ + A description... \ + ' % self.tenant_group + resp, content = header.request(url, "POST", body=body, + headers={"Content-Type": "application/xml", + "ACCEPT": "application/xml"}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(401, int(resp['status'])) + + def test_tenant_group_create_disabled_token(self): + header = httplib2.Http(".cache") + resp, content = util.create_tenant(self.tenant, str(self.auth_token)) + if int(resp['status']) == 200: + self.tenant = content['tenant']['id'] + + url = '%stenants/%s/groups' % (util.URL, self.tenant) + body = '{"group": { "id": "%s", \ + "description": "A description ..." } }' % self.tenant_group + resp, content = header.request(url, "POST", body=body, + headers={"Content-Type": "application/json", + "X-Auth-Token": self.disabled_token}) + + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(403, int(resp['status'])) + + def test_tenant_group_create_disabled_token_xml(self): + header = httplib2.Http(".cache") + resp, content = util.create_tenant_xml(self.tenant, + str(self.auth_token)) + content = etree.fromstring(content) + if int(resp['status']) == 200: + self.tenant = content.get('id') + + url = '%stenants/%s/groups' % (util.URL, self.tenant) + body = ' \ + \ + A description... \ + ' % self.tenant_group + resp, content = header.request(url, "POST", body=body, + headers={"Content-Type": "application/xml", + "X-Auth-Token": self.disabled_token, + "ACCEPT": "application/xml"}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(403, int(resp['status'])) + + def test_tenant_group_create_invalid_token(self): + header = httplib2.Http(".cache") + resp, content = util.create_tenant(self.tenant, str(self.auth_token)) + if int(resp['status']) == 200: + self.tenant = content['tenant']['id'] + + url = '%stenants/%s/groups' % (util.URL, self.tenant) + body = '{"group": { "id": "%s", \ + "description": "A description ..." } }' % self.tenant + resp, content = header.request(url, "POST", body=body, + headers={"Content-Type": "application/json", + "X-Auth-Token": 'nonexsitingtoken'}) + + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(404, int(resp['status'])) + + def test_tenant_group_create_invalid_token_xml(self): + header = httplib2.Http(".cache") + resp, content = util.create_tenant_xml(self.tenant, + str(self.auth_token)) + content = etree.fromstring(content) + if int(resp['status']) == 200: + self.tenant = content.get('id') + + url = '%stenants/%s/groups' % (util.URL, self.tenant) + body = ' \ + \ + A description... \ + ' % self.tenant_group + resp, content = header.request(url, "POST", body=body, + headers={"Content-Type": "application/xml", + "X-Auth-Token": 'nonexsitingtoken', + "ACCEPT": "application/xml"}) + + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(404, int(resp['status'])) + + +class GetTenantGroupsTest(TenantGroupTest): + + def test_get_tenant_groups(self): + header = httplib2.Http(".cache") + resp, content = util.create_tenant(self.tenant, str(self.auth_token)) + + resp, content = util.create_tenant_group(self.tenant_group, + self.tenant, + str(self.auth_token)) + + url = '%stenants/%s/groups' % (util.URL, self.tenant) + + resp, content = header.request(url, "GET", body='{}', + headers={"Content-Type": "application/json", + "X-Auth-Token": self.auth_token}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(200, int(resp['status'])) + + def test_get_tenant_groups_xml(self): + header = httplib2.Http(".cache") + resp, content = util.create_tenant(self.tenant, str(self.auth_token)) + + resp, content = util.create_tenant_group_xml(self.tenant_group, + self.tenant, + str(self.auth_token)) + url = '%stenants/%s/groups' % (util.URL, self.tenant) + resp, content = header.request(url, "GET", body='', + headers={"Content-Type": "application/xml", + "X-Auth-Token": self.auth_token, + "ACCEPT": "application/xml"}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(200, int(resp['status'])) + + def test_get_tenant_groups_unauthorized_token(self): + header = httplib2.Http(".cache") + resp, content = util.create_tenant(self.tenant, str(self.auth_token)) + + resp, content = util.create_tenant_group(self.tenant_group, + self.tenant, + str(self.auth_token)) + url = '%stenants/%s/groups' % (util.URL, self.tenant) + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body='{}', + headers={"Content-Type": "application/json", + "X-Auth-Token": self.token}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(401, int(resp['status'])) + + def test_get_tenant_groups_unauthorized_token_xml(self): + header = httplib2.Http(".cache") + resp, content = util.create_tenant(self.tenant, str(self.auth_token)) + resp, content = util.create_tenant_group(self.tenant_group, + self.tenant, + str(self.auth_token)) + url = '%stenants/%s/groups' % (util.URL, self.tenant) + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body='', + headers={"Content-Type": "application/xml", + "X-Auth-Token": self.token, + "ACCEPT": "application/xml"}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(401, int(resp['status'])) + + def test_get_tenant_groups_exp_token(self): + header = httplib2.Http(".cache") + resp, content = util.create_tenant(self.tenant, str(self.auth_token)) + resp, content = util.create_tenant_group(self.tenant_group, + self.tenant, + str(self.auth_token)) + url = '%stenants/%s/groups' % (util.URL, self.tenant) + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body='{}', + headers={"Content-Type": "application/json", + "X-Auth-Token": self.exp_auth_token}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(403, int(resp['status'])) + + def test_get_tenant_groups_exp_token_xml(self): + header = httplib2.Http(".cache") + resp, content = util.create_tenant(self.tenant, str(self.auth_token)) + resp, content = util.create_tenant_group(self.tenant_group, + self.tenant, + str(self.auth_token)) + url = '%stenants/%s/groups' % (util.URL, self.tenant) + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body='', + headers={"Content-Type": "application/xml", + "X-Auth-Token": self.exp_auth_token, + "ACCEPT": "application/xml"}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(403, int(resp['status'])) + + +class GetTenantGroupTest(TenantGroupTest): + + def test_get_tenant_group(self): + header = httplib2.Http(".cache") + resp, content = util.create_tenant(self.tenant, str(self.auth_token)) + resp, content = util.create_tenant_group(self.tenant_group, + self.tenant, + str(self.auth_token)) + url = '%stenants/%s/groups/%s' % (util.URL, self.tenant, + self.tenant_group) + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body='{}', + headers={"Content-Type": "application/json", + "X-Auth-Token": self.auth_token}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(200, int(resp['status'])) + + def test_get_tenant_group_xml(self): + header = httplib2.Http(".cache") + resp, content = util.create_tenant(self.tenant, str(self.auth_token)) + resp, content = util.create_tenant_group(self.tenant_group, + self.tenant, + str(self.auth_token)) + url = '%stenants/%s/groups/%s' % (util.URL, self.tenant, + self.tenant_group) + #test for Content-Type = application/xml + resp, content = header.request(url, "GET", body='', + headers={"Content-Type": "application/xml", + "X-Auth-Token": self.auth_token, + "ACCEPT": "application/xml"}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(200, int(resp['status'])) + + def test_get_tenant_group_bad(self): + header = httplib2.Http(".cache") + resp, content = util.create_tenant(self.tenant, str(self.auth_token)) + resp, content = util.create_tenant_group(self.tenant_group, + self.tenant, + str(self.auth_token)) + url = '%stenants/%s/groups/%s' % (util.URL, 'tenant_bad', + self.tenant_group) + + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body='{', + headers={"Content-Type": "application/json", + "X-Auth-Token": self.auth_token}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(404, int(resp['status'])) + + def test_get_tenant_group_bad_xml(self): + header = httplib2.Http(".cache") + resp, content = util.create_tenant(self.tenant, str(self.auth_token)) + resp, content = util.create_tenant_group(self.tenant_group, + self.tenant, + str(self.auth_token)) + url = '%stenants/%s/groups/%s' % (util.URL, 'tenant_bad', + self.tenant_group) + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body='{', + headers={"Content-Type": "application/xml", + "X-Auth-Token": self.auth_token, + "ACCEPT": "application/xml"}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(404, int(resp['status'])) + + def test_get_tenant_group_not_found(self): + header = httplib2.Http(".cache") + resp, content = util.create_tenant(self.tenant, str(self.auth_token)) + resp, content = util.create_tenant_group(self.tenant_group, + self.tenant, + str(self.auth_token)) + url = '%stenants/%s/groups/%s' % (util.URL, self.tenant, + 'nonexistinggroup') + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body='{}', + headers={"Content-Type": "application/json", + "X-Auth-Token": self.auth_token}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(404, int(resp['status'])) + + def test_get_tenant_group_not_found_xml(self): + header = httplib2.Http(".cache") + resp, content = util.create_tenant(self.tenant, str(self.auth_token)) + resp, content = util.create_tenant_group(self.tenant_group, + self.tenant, + str(self.auth_token)) + url = '%stenants/%s/groups/%s' % (util.URL, self.tenant, + 'nonexistinggroup') + + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body='', + headers={"Content-Type": "application/xml", + "X-Auth-Token": self.auth_token, + "ACCEPT": "application/xml"}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(404, int(resp['status'])) + + +class UpdateTenantGroupTest(TenantGroupTest): + + def test_update_tenant_group(self): + header = httplib2.Http(".cache") + resp, content = util.create_tenant(self.tenant, str(self.auth_token)) + resp, content = util.delete_tenant_group(self.tenant_group, + self.tenant, + str(self.auth_token)) + resp, content = util.create_tenant_group(self.tenant_group, + self.tenant, + str(self.auth_token)) + url = '%stenants/%s/groups/%s' % (util.URL, self.tenant, + self.tenant_group) + + data = '{"group": { "id":"%s","description": "A NEW description..." ,\ + "tenantId":"%s" }}' % (self.tenant_group, self.tenant) + #test for Content-Type = application/json + + resp, content = header.request(url, "PUT", body=data, + headers={"Content-Type": "application/json", + "X-Auth-Token": self.auth_token}) + + body = json.loads(content) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(200, int(resp['status'])) + self.assertEqual(self.tenant_group, body['group']['id']) + self.assertEqual('A NEW description...', body['group']['description']) + + def test_update_tenant_group_xml(self): + header = httplib2.Http(".cache") + resp = util.delete_tenant(self.tenant, str(self.auth_token)) + + resp, content = util.create_tenant(self.tenant, str(self.auth_token)) + + resp, content = util.delete_tenant_group(self.tenant_group, + self.tenant, + str(self.auth_token)) + + resp, content = util.create_tenant_group(self.tenant_group, + self.tenant, + str(self.auth_token)) + + url = '%stenants/%s/groups/%s' % (util.URL, self.tenant, + self.tenant_group) + + data = ' \ + A NEW description... \ + ' % (self.tenant, self.tenant_group) + + #test for Content-Type = application/json + resp, content = header.request(url, "PUT", body=data, + headers={"Content-Type": "application/xml", + "X-Auth-Token": self.auth_token, + "ACCEPT": "application/xml"}) + + body = etree.fromstring(content) + desc = body.find("{http://docs.openstack.org/identity/api/v2.0}description") + + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + + self.assertEqual(200, int(resp['status'])) + self.assertEqual(str(self.tenant_group), str(body.get('id'))) + self.assertEqual('A NEW description...', desc.text) + + def test_update_tenant_group_bad(self): + header = httplib2.Http(".cache") + resp, content = util.create_tenant(self.tenant, str(self.auth_token)) + resp, content = util.delete_tenant_group(self.tenant_group, + self.tenant, + str(self.auth_token)) + resp, content = util.create_tenant_group(self.tenant_group, + self.tenant, + str(self.auth_token)) + url = '%stenants/%s/groups/%s' % (util.URL, self.tenant, + self.tenant_group) + data = '{"group": { "description_bad": "A NEW description...",\ + "id":"%s","tenantId":"%s" }}' % (self.tenant_group, self.tenant) + #test for Content-Type = application/json + + resp, content = header.request(url, "PUT", body=data, + headers={"Content-Type": "application/json", + "X-Auth-Token": self.auth_token}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(400, int(resp['status'])) + + def test_update_tenant_group_bad_xml(self): + header = httplib2.Http(".cache") + resp, content = util.create_tenant(self.tenant, str(self.auth_token)) + resp, content = util.delete_tenant_group(self.tenant_group, + self.tenant, + str(self.auth_token)) + resp, content = util.create_tenant_group(self.tenant_group, + self.tenant, + str(self.auth_token)) + url = '%stenants/%s/groups/%s' % (util.URL, self.tenant, + self.tenant_group) + data = ' \ + \ + A NEW description... \ + ' % (self.tenant, self.tenant_group) + #test for Content-Type = application/json + resp, content = header.request(url, "PUT", body=data, + headers={"Content-Type": "application/xml", + "X-Auth-Token": self.auth_token, + "ACCEPT": "application/xml"}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(400, int(resp['status'])) + + def test_update_tenant_group_not_found(self): + header = httplib2.Http(".cache") + resp, content = util.create_tenant(self.tenant, str(self.auth_token)) + resp, content = util.delete_tenant_group(self.tenant_group, + self.tenant, + str(self.auth_token)) + resp, content = util.create_tenant_group(self.tenant_group, + self.tenant, + str(self.auth_token)) + url = '%stenants/%s/groups/NonexistingID' % (util.URL, self.tenant) + + data = '{"group": { "description": "A NEW description...",\ + "id":"NonexistingID", "tenantId"="test_tenant" }}' + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body=data, + headers={"Content-Type": "application/json", + "X-Auth-Token": self.auth_token}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(404, int(resp['status'])) + + def test_update_tenant_group_not_found_xml(self): + header = httplib2.Http(".cache") + resp, content = util.create_tenant(self.tenant, str(self.auth_token)) + url = '%stenants/%s/groups/NonexistingID' % (util.URL, self.tenant) + data = ' \ + \ + A NEW description... \ + ' + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body=data, + headers={"Content-Type": "application/xml", + "X-Auth-Token": self.auth_token, + "ACCEPT": "application/xml"}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(404, int(resp['status'])) + + +class DeleteTenantGroupTest(TenantGroupTest): + + def test_delete_tenant_group_not_found(self): + resp, content = util.delete_tenant_group("test_tenant_delete111", + self.tenant, + str(self.auth_token)) + self.assertEqual(404, int(resp['status'])) + + def test_delete_tenant_group_not_found_xml(self): + resp, content = util.delete_tenant_group_xml("test_tenant_delete111", + self.tenant, + str(self.auth_token)) + self.assertEqual(404, int(resp['status'])) + + def test_delete_tenant_group(self): + resp, content = util.create_tenant("test_tenant_delete", + str(self.auth_token)) + resp, content = util.create_tenant_group(self.tenant_group, + 'test_tenant_delete', + str(self.auth_token)) + resp, content = util.delete_tenant_group(self.tenant_group, + 'test_tenant_delete', + str(self.auth_token)) + self.assertEqual(204, int(resp['status'])) + resp = util.delete_tenant("test_tenant_delete", + str(self.auth_token)) + self.assertEqual(204, int(resp['status'])) + + +class AddUserTenantGroupTest(TenantGroupTest): + + def setUp(self): + self.tenant = 'test_tenant' + self.user = util.get_user() + self.userdisabled = util.get_userdisabled() + self.auth_token = util.get_auth_token() + self.exp_auth_token = util.get_exp_auth_token() + self.disabled_token = util.get_disabled_token() + self.tenant_group = 'test_tenant_group_add' + util.create_tenant(self.tenant, str(self.auth_token)) + util.create_user(self.tenant, self.user, self.auth_token) + util.add_user_json(self.tenant, self.user, self.auth_token) + self.token = util.get_token(self.user, 'secrete', self.tenant, + 'token') + + def tearDown(self): + resp, content = util.delete_user_tenant_group(self.tenant, + self.tenant_group, + self.user, + str(self.auth_token)) + + resp = util.delete_user(self.tenant, self.user, + str(self.auth_token)) + resp, content = util.delete_tenant_group(self.tenant_group, + self.tenant, + self.auth_token) + resp = util.delete_tenant(self.tenant, self.auth_token) + + def test_add_user_tenant_group(self): + resp, content = util.create_tenant(self.tenant, str(self.auth_token)) + + resp, content = util.create_tenant_group(self.tenant_group, + self.tenant, + str(self.auth_token)) + + resp, content = util.create_user(self.tenant, self.user, + str(self.auth_token)) + resp, content = util.add_user_tenant_group(self.tenant, + self.tenant_group, + self.user, + str(self.auth_token)) + + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + if int(resp['status']) not in (200, 201): + self.fail('Failed due to %d' % int(resp['status'])) + + def test_add_user_tenant_group_xml(self): + resp, content = util.create_tenant(self.tenant, str(self.auth_token)) + resp, content = util.create_tenant_group(self.tenant_group, + self.tenant, + str(self.auth_token)) + resp, content = util.create_user(self.tenant, self.user, + str(self.auth_token)) + resp, content = util.add_user_tenant_group_xml(self.tenant, + self.tenant_group, + self.user, + str(self.auth_token)) + + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + if int(resp['status']) not in (200, 201): + self.fail('Failed due to %d' % int(resp['status'])) + + def test_add_user_tenant_group_conflict(self): + resp, content = util.create_tenant(self.tenant, str(self.auth_token)) + resp, content = util.create_tenant_group(self.tenant_group, + self.tenant, + str(self.auth_token)) + resp, content = util.create_user(self.tenant, self.user, + str(self.auth_token)) + resp, content = util.add_user_tenant_group(self.tenant, + self.tenant_group, + self.user, + str(self.auth_token)) + resp, content = util.add_user_tenant_group(self.tenant, + self.tenant_group, + self.user, + str(self.auth_token)) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(409, int(resp['status'])) + + def test_add_user_tenant_group_conflict_xml(self): + resp, content = util.create_tenant(self.tenant, str(self.auth_token)) + resp, content = util.create_tenant_group(self.tenant_group, + self.tenant, + str(self.auth_token)) + resp, content = util.create_user(self.tenant, self.user, + str(self.auth_token)) + resp, content = util.add_user_tenant_group_xml(self.tenant, + self.tenant_group, + self.user, str(self.auth_token)) + resp, content = util.add_user_tenant_group_xml(self.tenant, + self.tenant_group, + self.user, + str(self.auth_token)) + + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(409, int(resp['status'])) + + def test_add_user_tenant_group_unauthorized(self): + resp, content = util.create_tenant(self.tenant, str(self.auth_token)) + resp, content = util.create_tenant_group(self.tenant_group, + self.tenant, + str(self.auth_token)) + resp, content = util.create_user(self.tenant, self.user, + str(self.auth_token)) + + resp, content = util.add_user_tenant_group(self.tenant, + self.tenant_group, + self.user, self.token) + + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(401, int(resp['status'])) + + def test_add_user_tenant_group_unauthorized_xml(self): + resp, content = util.create_tenant(self.tenant, str(self.auth_token)) + resp, content = util.create_tenant_group(self.tenant_group, + self.tenant, + str(self.auth_token)) + resp, content = util.create_user(self.tenant, self.user, + str(self.auth_token)) + + resp, content = util.add_user_tenant_group_xml(self.tenant, + self.tenant_group, + self.user, self.token) + + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(401, int(resp['status'])) + + def test_add_user_tenant_group_forbidden(self): + resp, content = util.create_tenant(self.tenant, str(self.auth_token)) + resp, content = util.create_tenant_group(self.tenant_group, + self.tenant, + str(self.auth_token)) + resp, content = util.create_user(self.tenant, self.user, + str(self.auth_token)) + + resp, content = util.add_user_tenant_group(self.tenant, + self.tenant_group, + self.user, + self.disabled_token) + + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(403, int(resp['status'])) + + def test_add_user_tenant_group_forbidden_xml(self): + resp, content = util.create_tenant(self.tenant, str(self.auth_token)) + resp, content = util.create_tenant_group(self.tenant_group, + self.tenant, + str(self.auth_token)) + resp, content = util.create_user(self.tenant, self.user, + str(self.auth_token)) + + resp, content = util.add_user_tenant_group_xml(self.tenant, + self.tenant_group, + self.user, + self.disabled_token) + + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(403, int(resp['status'])) + + +class GetUsersTenantGroupTest(TenantGroupTest): + + def setUp(self): + self.tenant = 'test_tenant' + self.user = util.get_user() + self.userdisabled = util.get_userdisabled() + self.auth_token = util.get_auth_token() + self.exp_auth_token = util.get_exp_auth_token() + self.disabled_token = util.get_disabled_token() + self.tenant_group = 'test_tenant_group_add' + util.create_tenant(self.tenant, str(self.auth_token)) + util.create_user(self.tenant, self.user, self.auth_token) + util.add_user_json(self.tenant, self.user, self.auth_token) + self.token = util.get_token(self.user, 'secrete', self.tenant, + 'token') + + def tearDown(self): + resp, content = util.delete_user_tenant_group(self.tenant, + self.tenant_group, + self.user, + str(self.auth_token)) + + resp = util.delete_user(self.tenant, self.user, + str(self.auth_token)) + resp, content = util.delete_tenant_group(self.tenant_group, + self.tenant, + self.auth_token) + util.delete_tenant(self.tenant, self.auth_token) + + def test_get_users_tenant_group(self): + resp, content = util.create_tenant(self.tenant, str(self.auth_token)) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + resp, content = util.create_tenant_group(self.tenant_group, + self.tenant, + str(self.auth_token)) + + util.create_user(self.tenant, self.user, + str(self.auth_token)) + util.add_user_tenant_group(self.tenant, + self.tenant_group, + self.user, + str(self.auth_token)) + resp, content = util.get_user_tenant_group(self.tenant, + self.tenant_group, + str(self.auth_token)) + + self.assertEqual(200, int(resp['status'])) + + def test_get_users_tenant_group_xml(self): + resp, content = util.create_tenant(self.tenant, str(self.auth_token)) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + util.create_tenant_group(self.tenant_group, + self.tenant, + str(self.auth_token)) + util.create_user(self.tenant, self.user, + str(self.auth_token)) + util.add_user_tenant_group_xml(self.tenant, + self.tenant_group, + self.user, + str(self.auth_token)) + resp, content = util.get_user_tenant_group_xml(self.tenant, + self.tenant_group, + str(self.auth_token)) + + self.assertEqual(200, int(resp['status'])) + + def test_get_users_tenant_group_unauthorized(self): + resp, content = util.create_tenant(self.tenant, str(self.auth_token)) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + util.create_tenant_group(self.tenant_group, + self.tenant, + str(self.auth_token)) + util.create_user(self.tenant, self.user, + str(self.auth_token)) + + util.add_user_tenant_group(self.tenant, + self.tenant_group, + self.user, + self.auth_token) + + resp, content = util.get_user_tenant_group(self.tenant, + self.tenant_group, + str(self.token)) + self.assertEqual(401, int(resp['status'])) + + def test_get_users_tenant_group_unauthorized_xml(self): + resp, content = util.create_tenant(self.tenant, str(self.auth_token)) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + + util.create_tenant_group(self.tenant_group, + self.tenant, + str(self.auth_token)) + util.create_user(self.tenant, self.user, + str(self.auth_token)) + + util.add_user_tenant_group(self.tenant, + self.tenant_group, + self.user, self.auth_token) + resp, content = util.get_user_tenant_group_xml(self.tenant, + self.tenant_group, + str(self.token)) + self.assertEqual(401, int(resp['status'])) + + def test_get_users_tenant_group_forbidden(self): + resp, content = util.create_tenant(self.tenant, str(self.auth_token)) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + util.create_tenant_group(self.tenant_group, + self.tenant, + str(self.auth_token)) + util.create_user(self.tenant, self.user, + str(self.auth_token)) + + util.add_user_tenant_group(self.tenant, + self.tenant_group, + self.user, self.auth_token) + resp, content = util.get_user_tenant_group(self.tenant, + self.tenant_group, + str(self.disabled_token)) + + self.assertEqual(403, int(resp['status'])) + + def test_get_users_tenant_group_forbidden_xml(self): + resp, content = util.create_tenant(self.tenant, str(self.auth_token)) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + util.create_tenant_group(self.tenant_group, + self.tenant, + str(self.auth_token)) + util.create_user(self.tenant, self.user, + str(self.auth_token)) + + util.add_user_tenant_group(self.tenant, + self.tenant_group, + self.user, self.auth_token) + resp, content = util.get_user_tenant_group_xml(self.tenant, + self.tenant_group, + str(self.disabled_token)) + + self.assertEqual(403, int(resp['status'])) + + def test_get_users_tenant_group_expired(self): + resp, content = util.create_tenant(self.tenant, str(self.auth_token)) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + util.create_tenant_group(self.tenant_group, + self.tenant, + str(self.auth_token)) + util.create_user(self.tenant, self.user, + str(self.auth_token)) + + util.add_user_tenant_group(self.tenant, + self.tenant_group, + self.user, self.auth_token) + resp, content = util.get_user_tenant_group(self.tenant, + self.tenant_group, + str(self.exp_auth_token)) + self.assertEqual(403, int(resp['status'])) + + def test_get_users_tenant_group_expired_xml(self): + resp, content = util.create_tenant(self.tenant, str(self.auth_token)) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + util.create_tenant_group(self.tenant_group, + self.tenant, + str(self.auth_token)) + util.create_user(self.tenant, self.user, + str(self.auth_token)) + + util.add_user_tenant_group(self.tenant, + self.tenant_group, + self.user, self.auth_token) + resp, content = util.get_user_tenant_group_xml(self.tenant, + self.tenant_group, + str(self.exp_auth_token)) + + self.assertEqual(403, int(resp['status'])) + + +class DeleteUsersTenantGroupTest(TenantGroupTest): + + def test_delete_user_tenant_group(self): + resp, content = util.create_tenant(self.tenant, str(self.auth_token)) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + util.create_tenant_group(self.tenant_group, + self.tenant, + str(self.auth_token)) + util.create_user(self.tenant, self.user, + str(self.auth_token)) + util.add_user_tenant_group(self.tenant, + self.tenant_group, + self.user, + str(self.auth_token)) + resp, content = util.delete_user_tenant_group(self.tenant, + self.tenant_group, + self.user, + str(self.auth_token)) + + self.assertEqual(204, int(resp['status'])) + + def test_delete_user_tenant_group_xml(self): + resp, content = util.create_tenant(self.tenant, str(self.auth_token)) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + util.create_tenant_group(self.tenant_group, + self.tenant, + str(self.auth_token)) + util.create_user(self.tenant, self.user, + str(self.auth_token)) + util.add_user_tenant_group_xml(self.tenant, + self.tenant_group, + self.user, + str(self.auth_token)) + resp, content = util.delete_user_tenant_group_xml(self.tenant, + self.tenant_group, + self.user, + str(self.auth_token)) + + self.assertEqual(204, int(resp['status'])) + + def test_delete_user_tenant_group_notfound(self): + resp, content = util.delete_user_tenant_group(self.tenant, + self.tenant_group, + 'NonExistinguser', + str(self.auth_token)) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(404, int(resp['status'])) + + def test_delete_user_tenant_group_notfound_xml(self): + resp, content = util.delete_user_tenant_group_xml(self.tenant, + self.tenant_group, + 'NonExistinguser', + str(self.auth_token)) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(404, int(resp['status'])) + +if __name__ == '__main__': + unittest.main() diff --git a/keystone/test/unit/test_tenants.py b/keystone/test/unit/test_tenants.py new file mode 100644 index 00000000..bc639904 --- /dev/null +++ b/keystone/test/unit/test_tenants.py @@ -0,0 +1,661 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 +# Copyright (c) 2010-2011 OpenStack, LLC. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +import httplib2 +import json +from lxml import etree +import os +import sys +sys.path.append(os.path.abspath(os.path.join(os.path.abspath(__file__), + '..', '..', '..', '..', 'keystone'))) +import unittest + +import test_common as utils + + +class TenantTest(unittest.TestCase): + + def setUp(self): + self.tenant = 'test_tenant' + self.auth_token = utils.get_auth_token() + self.user = utils.get_user() + self.userdisabled = utils.get_userdisabled() + self.exp_auth_token = utils.get_exp_auth_token() + self.disabled_token = utils.get_disabled_token() + utils.create_tenant(self.tenant, str(self.auth_token)) + utils.create_user(self.tenant, self.user, self.auth_token) + utils.add_user_json(self.tenant, self.user, self.auth_token) + self.token = utils.get_token(self.user, 'secrete', self.tenant, + 'token') + + def tearDown(self): + utils.delete_user(self.tenant, self.user, self.auth_token) + utils.delete_tenant(self.tenant, self.auth_token) + + +class CreateTenantTest(TenantTest): + + def test_tenant_create(self): + utils.delete_user(self.tenant, self.user, self.auth_token) + utils.delete_tenant(self.tenant, str(self.auth_token)) + resp, content = utils.create_tenant(self.tenant, str(self.auth_token)) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + + if int(resp['status']) not in (200, 201): + + self.fail('Failed due to %d' % int(resp['status'])) + + def test_tenant_create_xml(self): + utils.delete_user(self.tenant, self.user, self.auth_token) + utils.delete_tenant_xml(self.tenant, + str(self.auth_token)) + resp, content = utils.create_tenant_xml(self.tenant, + str(self.auth_token)) + content = etree.fromstring(content) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + if int(resp['status']) not in (200, 201): + self.fail('Failed due to %d' % int(resp['status'])) + + def test_tenant_create_again(self): + + resp, content = utils.create_tenant(self.tenant, + str(self.auth_token)) + if int(resp['status']) == 200: + self.tenant = content['tenant']['id'] + resp, content = utils.create_tenant(self.tenant, + str(self.auth_token)) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(409, int(resp['status'])) + + def test_tenant_create_again_xml(self): + + resp, content = utils.create_tenant_xml(self.tenant, + str(self.auth_token)) + resp, content = utils.create_tenant_xml(self.tenant, + str(self.auth_token)) + content = etree.fromstring(content) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(409, int(resp['status'])) + + def test_tenant_create_forbidden_token(self): + header = httplib2.Http(".cache") + resp, content = utils.create_tenant(self.tenant, str(self.auth_token)) + if int(resp['status']) == 200: + self.tenant = content['tenant']['id'] + + url = '%stenants' % (utils.URL) + body = {"tenant": {"id": self.tenant, + "description": "A description ...", + "enabled": True}} + resp, content = header.request(url, "POST", body=json.dumps(body), + headers={"Content-Type": "application/json", + "X-Auth-Token": self.token}) + + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(401, int(resp['status'])) + + def test_tenant_create_forbidden_token_xml(self): + header = httplib2.Http(".cache") + resp, content = utils.create_tenant_xml(self.tenant, + str(self.auth_token)) + content = etree.fromstring(content) + if int(resp['status']) == 200: + self.tenant = content.get('id') + + url = '%stenants' % (utils.URL) + body = ' \ + \ + A description... \ + ' % self.tenant + resp, content = header.request(url, "POST", body=body, + headers={"Content-Type": "application/xml", + "X-Auth-Token": self.token, + "ACCEPT": "application/xml"}) + + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(401, int(resp['status'])) + + def test_tenant_create_expired_token(self): + header = httplib2.Http(".cache") + resp, content = utils.create_tenant(self.tenant, + str(self.auth_token)) + if int(resp['status']) == 200: + self.tenant = content['tenant']['id'] + url = '%stenants' % (utils.URL) + body = {"tenant": {"id": self.tenant, + "description": "A description ...", + "enabled": True}} + resp, content = header.request(url, "POST", body=json.dumps(body), + headers={"Content-Type": "application/json", + "X-Auth-Token": self.exp_auth_token}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(403, int(resp['status'])) + + def test_tenant_create_expired_token_xml(self): + header = httplib2.Http(".cache") + resp, content = utils.create_tenant_xml(self.tenant, + str(self.auth_token)) + content = etree.fromstring(content) + if int(resp['status']) == 200: + self.tenant = content.get('id') + + url = '%stenants' % (utils.URL) + body = ' \ + \ + A description... \ + ' % self.tenant + + resp, content = header.request(url, "POST", body=body, + headers={"Content-Type": "application/xml", + "X-Auth-Token": self.exp_auth_token, + "ACCEPT": "application/xml"}) + + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(403, int(resp['status'])) + + def test_tenant_create_missing_token(self): + header = httplib2.Http(".cache") + resp, content = utils.create_tenant(self.tenant, + str(self.auth_token)) + if int(resp['status']) == 200: + self.tenant = content['tenant']['id'] + + url = '%stenants' % (utils.URL) + body = {"tenant": {"id": self.tenant, + "description": "A description ...", + "enabled": True}} + resp, content = header.request(url, "POST", body=json.dumps(body), + headers={"Content-Type": "application/json"}) + + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(401, int(resp['status'])) + + def test_tenant_create_missing_token_xml(self): + header = httplib2.Http(".cache") + resp, content = utils.create_tenant_xml(self.tenant, + str(self.auth_token)) + content = etree.fromstring(content) + if int(resp['status']) == 200: + self.tenant = content.get('id') + url = '%stenants' % (utils.URL) + body = ' \ + \ + A description... \ + ' % self.tenant + resp, content = header.request(url, "POST", body=body, + headers={"Content-Type": "application/xml", + "ACCEPT": "application/xml"}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(401, int(resp['status'])) + + def test_tenant_create_disabled_token(self): + header = httplib2.Http(".cache") + resp, content = utils.create_tenant(self.tenant, + str(self.auth_token)) + if int(resp['status']) == 200: + self.tenant = content['tenant']['id'] + + url = '%stenants' % (utils.URL) + body = '{"tenant": { "id": "%s", \ + "description": "A description ...", "enabled"\ + :true } }' % self.tenant + resp, content = header.request(url, "POST", body=body, + headers={"Content-Type": "application/json", + "X-Auth-Token": self.disabled_token}) + + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(403, int(resp['status'])) + + def test_tenant_create_disabled_token_xml(self): + header = httplib2.Http(".cache") + resp, content = utils.create_tenant_xml(self.tenant, + str(self.auth_token)) + content = etree.fromstring(content) + if int(resp['status']) == 200: + self.tenant = content.get('id') + url = '%stenants' % (utils.URL) + body = ' \ + \ + A description... \ + ' % self.tenant + resp, content = header.request(url, "POST", body=body, + headers={"Content-Type": "application/xml", + "X-Auth-Token": self.disabled_token, + "ACCEPT": "application/xml"}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(403, int(resp['status'])) + + def test_tenant_create_invalid_token(self): + header = httplib2.Http(".cache") + resp, content = utils.create_tenant(self.tenant, + str(self.auth_token)) + if int(resp['status']) == 200: + self.tenant = content['tenant']['id'] + + url = '%stenants' % (utils.URL) + body = '{"tenant": { "id": "%s", \ + "description": "A description ...", "enabled"\ + :true } }' % self.tenant + resp, content = header.request(url, "POST", body=body, + headers={"Content-Type": "application/json", + "X-Auth-Token": 'nonexsitingtoken'}) + + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(404, int(resp['status'])) + + def test_tenant_create_invalid_token_xml(self): + header = httplib2.Http(".cache") + resp, content = utils.create_tenant_xml(self.tenant, + str(self.auth_token)) + content = etree.fromstring(content) + if int(resp['status']) == 200: + self.tenant = content.get('id') + + url = '%stenants' % (utils.URL) + body = ' \ + \ + A description... \ + ' % self.tenant + resp, content = header.request(url, "POST", body=body, + headers={"Content-Type": "application/xml", + "X-Auth-Token": 'nonexsitingtoken', + "ACCEPT": "application/xml"}) + + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(404, int(resp['status'])) + + +class GetTenantsTest(TenantTest): + + def test_get_tenants_using_admin_token(self): + header = httplib2.Http(".cache") + resp, content = utils.create_tenant(self.tenant, str(self.auth_token)) + url = '%stenants' % (utils.URL) + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body='{}', + headers={"Content-Type": "application/json", + "X-Auth-Token": self.auth_token}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(200, int(resp['status'])) + + def test_get_tenants_using_admin_token_xml(self): + header = httplib2.Http(".cache") + resp, content = utils.create_tenant(self.tenant, str(self.auth_token)) + url = '%stenants' % (utils.URL) + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body='', + headers={"Content-Type": "application/xml", + "X-Auth-Token": self.auth_token, + "ACCEPT": "application/xml"}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(200, int(resp['status'])) + + def test_get_tenants_using_user_token(self): + header = httplib2.Http(".cache") + resp, content = utils.create_tenant(self.tenant, str(self.auth_token)) + url = '%stenants' % (utils.URL) + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body='{}', + headers={"Content-Type": "application/json", + "X-Auth-Token": self.token}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(200, int(resp['status'])) + + def test_get_tenants_using_user_token_xml(self): + header = httplib2.Http(".cache") + resp, content = utils.create_tenant(self.tenant, str(self.auth_token)) + url = '%stenants' % (utils.URL) + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body='', + headers={"Content-Type": "application/xml", + "X-Auth-Token": self.token, + "ACCEPT": "application/xml"}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(200, int(resp['status'])) + + def test_get_tenants_exp_token(self): + header = httplib2.Http(".cache") + resp, content = utils.create_tenant(self.tenant, str(self.auth_token)) + url = '%stenants' % (utils.URL) + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body='{}', + headers={"Content-Type": "application/json", + "X-Auth-Token": self.exp_auth_token}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(403, int(resp['status'])) + + def test_get_tenants_exp_token_xml(self): + header = httplib2.Http(".cache") + resp, content = utils.create_tenant(self.tenant, str(self.auth_token)) + url = '%stenants' % (utils.URL) + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body='', + headers={"Content-Type": "application/xml", + "X-Auth-Token": self.exp_auth_token, + "ACCEPT": "application/xml"}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(403, int(resp['status'])) + + +class GetTenantTest(TenantTest): + + def test_get_tenant(self): + header = httplib2.Http(".cache") + resp, content = utils.create_tenant(self.tenant, str(self.auth_token)) + url = '%stenants/%s' % (utils.URL, self.tenant) + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body='{}', + headers={"Content-Type": "application/json", + "X-Auth-Token": self.auth_token}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(200, int(resp['status'])) + + def test_get_tenant_xml(self): + header = httplib2.Http(".cache") + resp, content = utils.create_tenant(self.tenant, str(self.auth_token)) + url = '%stenants/%s' % (utils.URL, self.tenant) + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body='', + headers={"Content-Type": "application/xml", + "X-Auth-Token": self.auth_token, + "ACCEPT": "application/xml"}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(200, int(resp['status'])) + + def test_get_tenant_bad(self): + header = httplib2.Http(".cache") + resp, content = utils.create_tenant(self.tenant, str(self.auth_token)) + url = '%stenants/%s' % (utils.URL, 'tenant_bad') + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body='', + headers={"Content-Type": "application/json", + "X-Auth-Token": self.auth_token}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(404, int(resp['status'])) + + def test_get_tenant_bad_xml(self): + header = httplib2.Http(".cache") + resp, content = utils.create_tenant(self.tenant, str(self.auth_token)) + url = '%stenants/%s' % (utils.URL, 'tenant_bad') + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body='', + headers={"Content-Type": "application/xml", + "X-Auth-Token": self.auth_token, + "ACCEPT": "application/xml"}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(404, int(resp['status'])) + + def test_get_tenant_not_found(self): + header = httplib2.Http(".cache") + resp, content = utils.create_tenant(self.tenant, str(self.auth_token)) + url = '%stenants/NonexistingID' % (utils.URL) + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body='{}', + headers={"Content-Type": "application/json", + "X-Auth-Token": self.auth_token}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(404, int(resp['status'])) + + def test_get_tenant_not_found_xml(self): + header = httplib2.Http(".cache") + resp, content = utils.create_tenant(self.tenant, str(self.auth_token)) + url = '%stenants/NonexistingID' % (utils.URL) + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body='', + headers={"Content-Type": "application/xml", + "X-Auth-Token": self.auth_token, + "ACCEPT": "application/xml"}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(404, int(resp['status'])) + + +class UpdateTenantTest(TenantTest): + + def test_update_tenant(self): + header = httplib2.Http(".cache") + resp, content = utils.create_tenant(self.tenant, str(self.auth_token)) + url = '%stenants/%s' % (utils.URL, self.tenant) + data = '{"tenant": { "description": "A NEW description..." ,\ + "enabled":true }}' + #test for Content-Type = application/json + resp, content = header.request(url, "PUT", body=data, + headers={"Content-Type": "application/json", + "X-Auth-Token": self.auth_token}) + body = json.loads(content) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(200, int(resp['status'])) + self.assertEqual(self.tenant, body['tenant']['id']) + self.assertEqual('A NEW description...', body['tenant']['description']) + + def test_update_tenant_xml(self): + header = httplib2.Http(".cache") + resp, content = utils.create_tenant_xml(self.tenant, + str(self.auth_token)) + url = '%stenants/%s' % (utils.URL, self.tenant) + data = ' \ + \ + A NEW description... \ + ' + + #test for Content-Type = application/json + resp, content = header.request(url, "PUT", body=data, + headers={"Content-Type": "application/xml", + "X-Auth-Token": self.auth_token, + "ACCEPT": "application/xml"}) + body = etree.fromstring(content) + desc = body.find("{http://docs.openstack.org/identity/api/v2.0}description") + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(200, int(resp['status'])) + self.assertEqual(self.tenant, body.get('id')) + self.assertEqual('A NEW description...', desc.text) + + def test_update_tenant_bad(self): + header = httplib2.Http(".cache") + resp, content = utils.create_tenant(self.tenant, str(self.auth_token)) + url = '%stenants/%s' % (utils.URL, self.tenant) + data = '{"tenant": { "description_bad": "A NEW description...",\ + "enabled":true }}' + #test for Content-Type = application/json + + resp, content = header.request(url, "PUT", body=data, + headers={"Content-Type": "application/json", + "X-Auth-Token": self.auth_token}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(400, int(resp['status'])) + + def test_update_tenant_bad_xml(self): + header = httplib2.Http(".cache") + resp, content = utils.create_tenant(self.tenant, str(self.auth_token)) + url = '%stenants/%s' % (utils.URL, self.tenant) + data = ' \ + \ + A NEW description... \ + ' + #test for Content-Type = application/json + resp, content = header.request(url, "PUT", body=data, + headers={"Content-Type": "application/xml", + "X-Auth-Token": self.auth_token, + "ACCEPT": "application/xml"}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(400, int(resp['status'])) + + def test_update_tenant_not_found(self): + header = httplib2.Http(".cache") + resp, content = utils.create_tenant(self.tenant, str(self.auth_token)) + url = '%stenants/NonexistingID' % (utils.URL) + data = '{"tenant": { "description": "A NEW description...",\ + "enabled":true }}' + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body=data, + headers={"Content-Type": "application/json", + "X-Auth-Token": self.auth_token}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(404, int(resp['status'])) + + def test_update_tenant_not_found_xml(self): + header = httplib2.Http(".cache") + resp, content = utils.create_tenant(self.tenant, str(self.auth_token)) + url = '%stenants/NonexistingID' % (utils.URL) + data = ' \ + \ + A NEW description... \ + ' + #test for Content-Type = application/json + resp, content = header.request(url, "GET", body=data, + headers={"Content-Type": "application/xml", + "X-Auth-Token": self.auth_token, + "ACCEPT": "application/xml"}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(404, int(resp['status'])) + + +class DeleteTenantTest(TenantTest): + + def test_delete_tenant_not_found(self): + #resp,content=utils.create_tenant("test_tenant_delete", + # str(self.auth_token)) + resp = utils.delete_tenant("test_tenant_delete111", + str(self.auth_token)) + self.assertEqual(404, int(resp['status'])) + + def test_delete_tenant_not_found_xml(self): + #resp,content=utils.create_tenant("test_tenant_delete", + # str(self.auth_token)) + resp = utils.delete_tenant_xml("test_tenant_delete111", + str(self.auth_token)) + self.assertEqual(404, int(resp['status'])) + + def test_delete_tenant(self): + resp, content = utils.create_tenant("test_tenant_delete", + str(self.auth_token)) + resp = utils.delete_tenant("test_tenant_delete", + str(self.auth_token)) + self.assertEqual(204, int(resp['status'])) + + def test_delete_tenant_xml(self): + resp, content = utils.create_tenant_xml("test_tenant_delete", + str(self.auth_token)) + resp = utils.delete_tenant_xml("test_tenant_delete", + str(self.auth_token)) + self.assertEqual(204, int(resp['status'])) + +if __name__ == '__main__': + unittest.main() diff --git a/keystone/test/unit/test_token.py b/keystone/test/unit/test_token.py new file mode 100644 index 00000000..0754f777 --- /dev/null +++ b/keystone/test/unit/test_token.py @@ -0,0 +1,173 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 +# Copyright (c) 2010-2011 OpenStack, LLC. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +import httplib2 +import os +import sys +sys.path.append(os.path.abspath(os.path.join(os.path.abspath(__file__), + '..', '..', '..', '..', 'keystone'))) +import unittest +import test_common as utils +import json +import keystone.logic.types.fault as fault +from lxml import etree + +class ValidateToken(unittest.TestCase): + + def setUp(self): + self.tenant = utils.get_tenant() + self.user = 'joeuser' + self.token = utils.get_token('joeuser', 'secrete', self.tenant, + 'token') + #self.user = utils.get_user() + #self.userdisabled = utils.get_userdisabled() + self.auth_token = utils.get_auth_token() + self.exp_auth_token = utils.get_exp_auth_token() + #self.disabled_token = utils.get_disabled_token() + resp, content = utils.create_role_ref(self.user, 'Admin', self.tenant, str(self.auth_token)) + obj = json.loads(content) + if not "roleRef" in obj: + raise fault.BadRequestFault("Expecting RoleRef") + roleRef = obj["roleRef"] + if not "id" in roleRef: + self.role_ref_id = None + else: + self.role_ref_id = roleRef["id"] + + + def tearDown(self): + resp, content = utils.delete_role_ref(self.user, self.role_ref_id, self.auth_token) + utils.delete_token(self.token, self.auth_token) + + def test_validate_token_true(self): + header = httplib2.Http(".cache") + + url = '%stokens/%s?belongsTo=%s' % (utils.URL, self.token, self.tenant) + resp, content = header.request(url, "GET", body='', + headers={"Content-Type": "application/json", + "X-Auth-Token": self.auth_token}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(200, int(resp['status'])) + self.assertEqual('application/json', utils.content_type(resp)) + #verify content + obj = json.loads(content) + if not "auth" in obj: + raise self.fail("Expecting Auth") + role_refs = obj["auth"]["user"]["roleRefs"] + role_ref = role_refs[0] + role_ref_id = role_ref["id"] + self.assertEqual(self.role_ref_id, role_ref_id) + + def test_validate_token_true_xml(self): + header = httplib2.Http(".cache") + url = '%stokens/%s?belongsTo=%s' % (utils.URL, self.token, self.tenant) + resp, content = header.request(url, "GET", body='', + headers={"Content-Type": "application/xml", + "X-Auth-Token": self.auth_token, + "ACCEPT": "application/xml"}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(200, int(resp['status'])) + self.assertEqual('application/xml', utils.content_type(resp)) + #verify content + dom = etree.Element("root") + dom.append(etree.fromstring(content)) + auth = dom.find("{http://docs.openstack.org/identity/api/v2.0}" \ + "auth") + if auth == None: + self.fail("Expecting Auth") + + user = auth.find("{http://docs.openstack.org/identity/api/v2.0}" \ + "user") + if user == None: + self.fail("Expecting User") + roleRefs = user.find("{http://docs.openstack.org/identity/api/v2.0}" \ + "roleRefs") + if roleRefs == None: + self.fail("Expecting Role Refs") + roleRef = roleRefs.find("{http://docs.openstack.org/identity/api/v2.0}" \ + "roleRef") + if roleRef == None: + self.fail("Expecting Role Refs") + self.assertEqual(str(self.role_ref_id), roleRef.get("id")) + + def test_validate_token_expired(self): + header = httplib2.Http(".cache") + url = '%stokens/%s?belongsTo=%s' % (utils.URL, self.exp_auth_token, + self.tenant) + resp, content = header.request(url, "GET", body='', + headers={"Content-Type": "application/json", + "X-Auth-Token": self.exp_auth_token}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(403, int(resp['status'])) + self.assertEqual('application/json', utils.content_type(resp)) + + def test_validate_token_expired_xml(self): + header = httplib2.Http(".cache") + + url = '%stokens/%s?belongsTo=%s' % (utils.URL, self.exp_auth_token, + self.tenant) + resp, content = header.request(url, "GET", body='', + headers={"Content-Type": "application/xml", + "X-Auth-Token": self.exp_auth_token, + "ACCEPT": "application/xml"}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(403, int(resp['status'])) + self.assertEqual('application/xml', utils.content_type(resp)) + + def test_validate_token_invalid(self): + header = httplib2.Http(".cache") + url = '%stokens/%s?belongsTo=%s' % (utils.URL, 'NonExistingToken', + self.tenant) + resp, content = header.request(url, "GET", body='', + headers={"Content-Type": "application/json", + "X-Auth-Token": self.auth_token}) + + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(401, int(resp['status'])) + self.assertEqual('application/json', utils.content_type(resp)) + + def test_validate_token_invalid_xml(self): + header = httplib2.Http(".cache") + url = '%stokens/%s?belongsTo=%s' % (utils.URL, 'NonExistingToken', + self.tenant) + resp, content = header.request(url, "GET", body='', + headers={"Content-Type": "application/json", + "X-Auth-Token": self.auth_token}) + if int(resp['status']) == 500: + self.fail('Identity Fault') + elif int(resp['status']) == 503: + self.fail('Service Not Available') + self.assertEqual(401, int(resp['status'])) + self.assertEqual('application/json', utils.content_type(resp)) + +if __name__ == '__main__': + unittest.main() diff --git a/keystone/test/unit/test_users.py b/keystone/test/unit/test_users.py new file mode 100644 index 00000000..083da21f --- /dev/null +++ b/keystone/test/unit/test_users.py @@ -0,0 +1,1584 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 +# Copyright (c) 2010-2011 OpenStack, LLC. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +import httplib2 +import json +from lxml import etree +import os +import sys +sys.path.append(os.path.abspath(os.path.join(os.path.abspath(__file__), + '..', '..', '..', '..', 'keystone'))) +import unittest + +import test_common as utils +from test_common import URL + + +class UserTest(unittest.TestCase): + + def setUp(self): + self.tenant = utils.get_tenant() + self.password = utils.get_password() + self.email = utils.get_email() + self.user = utils.get_user() + self.userdisabled = utils.get_userdisabled() + self.auth_token = utils.get_auth_token() + self.exp_auth_token = utils.get_exp_auth_token() + self.disabled_token = utils.get_disabled_token() + self.missing_token = utils.get_none_token() + self.invalid_token = utils.get_non_existing_token() + utils.create_tenant(self.tenant, str(self.auth_token)) + utils.add_user_json(self.tenant, self.user, self.auth_token) + self.token = utils.get_token(self.user, 'secrete', self.tenant, + 'token') + + def tearDown(self): + utils.delete_user(self.tenant, self.user, str(self.auth_token)) + + +class CreateUserTest(UserTest): + + def test_a_user_create_json(self): + + resp = utils.delete_user(self.tenant, self.user, str(self.auth_token)) + + resp, content = utils.create_user(self.tenant, 'test_user1', + str(self.auth_token)) + self.user = 'test_user1' + resp_val = int(resp['status']) + utils.handle_user_resp(self, content, resp_val, + utils.content_type(resp)) + self.assertEqual(201, resp_val) + + def test_a_user_create_xml(self): + utils.delete_user_xml(self.tenant, self.user, str(self.auth_token)) + resp, content = utils.create_user_xml(self.tenant, 'test_user1', + str(self.auth_token)) + self.user = 'test_user1' + resp_val = int(resp['status']) + utils.handle_user_resp(self, content, resp_val, + utils.content_type(resp)) + self.assertEqual(201, resp_val) + self.assertEqual('application/xml', utils.content_type(resp)) + + def test_a_user_create_json_disabled_tenant(self): + resp, content = utils.create_user('0000', self.user, + str(self.auth_token)) + resp_val = int(resp['status']) + utils.handle_user_resp(self, content, resp_val, + utils.content_type(resp)) + self.assertEqual(403, resp_val) + + def test_a_user_create_json_disabled_tenant_xml(self): + resp, content = utils.create_user_xml('0000', self.user, + str(self.auth_token)) + resp_val = int(resp['status']) + utils.handle_user_resp(self, content, resp_val, + utils.content_type(resp)) + self.assertEqual(403, resp_val) + self.assertEqual('application/xml', utils.content_type(resp)) + + def test_a_user_create_again_json(self): + resp, content = utils.create_user(self.tenant, self.user, + str(self.auth_token)) + resp_val = int(resp['status']) + utils.handle_user_resp(self, content, resp_val, + utils.content_type(resp)) + resp, content = utils.create_user(self.tenant, self.user, + str(self.auth_token)) + self.assertEqual(409, int(resp['status'])) + + def test_a_user_create_again_xml(self): + utils.create_user_xml(self.tenant, self.user, + str(self.auth_token)) + resp, content = utils.create_user_xml(self.tenant, self.user, + str(self.auth_token)) + content = etree.fromstring(content) + resp_val = int(resp['status']) + utils.handle_user_resp(self, content, resp_val, + utils.content_type(resp)) + self.assertEqual(409, int(resp['status'])) + self.assertEqual('application/xml', utils.content_type(resp)) + + def test_a_user_create_email_conflict(self): + utils.create_user(self.tenant, self.user, str(self.auth_token), + self.email) + resp, content = utils.create_user(self.tenant, self.user, + str(self.auth_token), + self.email) + self.assertEqual(409, int(resp['status'])) + + def test_a_user_create_email_conflict_xml(self): + utils.create_user_xml(self.tenant, + self.user, + str(self.auth_token), + self.email) + resp, content = utils.create_user_xml(self.tenant, self.user, + str(self.auth_token), + self.email) + content = etree.fromstring(content) + resp_val = int(resp['status']) + utils.handle_user_resp(self, content, resp_val, + utils.content_type(resp)) + self.assertEqual(409, int(resp['status'])) + self.assertEqual('application/xml', utils.content_type(resp)) + + def test_a_user_create_expired_token(self): + resp, content = utils.create_user(self.tenant, self.user, + str(self.exp_auth_token)) + resp_val = int(resp['status']) + utils.handle_user_resp(self, content, resp_val, + utils.content_type(resp)) + self.assertEqual(403, int(resp['status'])) + + def test_a_user_create_expired_token_xml(self): + resp, content = utils.create_user_xml(self.tenant, self.user, + str(self.exp_auth_token)) + resp_val = int(resp['status']) + utils.handle_user_resp(self, content, resp_val, + utils.content_type(resp)) + self.assertEqual(403, int(resp['status'])) + self.assertEqual('application/xml', utils.content_type(resp)) + + def test_a_user_create_disabled_token(self): + resp, content = utils.create_user(self.tenant, self.user, + str(self.disabled_token)) + resp_val = int(resp['status']) + utils.handle_user_resp(self, content, resp_val, + utils.content_type(resp)) + self.assertEqual(403, int(resp['status'])) + + def test_a_user_create_disabled_token_xml(self): + resp, content = utils.create_user_xml(self.tenant, self.user, + str(self.disabled_token)) + resp_val = int(resp['status']) + utils.handle_user_resp(self, content, resp_val, + utils.content_type(resp)) + self.assertEqual(403, int(resp['status'])) + self.assertEqual('application/xml', utils.content_type(resp)) + + def test_a_user_create_missing_token(self): + resp, content = utils.create_user(self.tenant, self.user, + str(self.missing_token)) + resp_val = int(resp['status']) + utils.handle_user_resp(self, content, resp_val, + utils.content_type(resp)) + self.assertEqual(401, int(resp['status'])) + + def test_a_user_create_missing_token_xml(self): + resp, content = utils.create_user_xml(self.tenant, self.user, + str(self.missing_token)) + resp_val = int(resp['status']) + utils.handle_user_resp(self, content, resp_val, + utils.content_type(resp)) + self.assertEqual(401, int(resp['status'])) + self.assertEqual('application/xml', utils.content_type(resp)) + + def test_a_user_create_invalid_token(self): + resp, content = utils.create_user(self.tenant, self.user, + str(self.invalid_token)) + resp_val = int(resp['status']) + utils.handle_user_resp(self, content, resp_val, + utils.content_type(resp)) + self.assertEqual(404, int(resp['status'])) + + def test_a_user_create_invalid_token_xml(self): + resp, content = utils.create_user_xml(self.tenant, self.user, + str(self.invalid_token)) + resp_val = int(resp['status']) + utils.handle_user_resp(self, content, resp_val, + utils.content_type(resp)) + self.assertEqual(404, int(resp['status'])) + self.assertEqual('application/xml', utils.content_type(resp)) + + +class GetUserTest(UserTest): + + def test_a_user_get(self): + utils.create_user(self.tenant, self.user, str(self.auth_token)) + resp, content = utils.user_get_json(self.tenant, self.user, + str(self.auth_token)) + resp_val = int(resp['status']) + utils.handle_user_resp(self, content, resp_val, + utils.content_type(resp)) + self.assertEqual(200, resp_val) + + def test_a_user_get_xml(self): + utils.create_user(self.tenant, self.user, str(self.auth_token)) + resp, content = utils.user_get_xml(self.tenant, self.user, + str(self.auth_token)) + resp_val = int(resp['status']) + utils.handle_user_resp(self, content, resp_val, + utils.content_type(resp)) + self.assertEqual(200, resp_val) + self.assertEqual('application/xml', utils.content_type(resp)) + + def test_a_user_get_expired_token(self): + utils.create_user(self.tenant, self.user, str(self.auth_token)) + resp, content = utils.user_get_json(self.tenant, self.user, + str(self.exp_auth_token)) + resp_val = int(resp['status']) + utils.handle_user_resp(self, content, resp_val, + utils.content_type(resp)) + self.assertEqual(403, resp_val) + + def test_a_user_get_expired_token_xml(self): + utils.create_user(self.tenant, self.user, str(self.auth_token)) + resp, content = utils.user_get_xml(self.tenant, self.user, + str(self.exp_auth_token)) + resp_val = int(resp['status']) + utils.handle_user_resp(self, content, resp_val, + utils.content_type(resp)) + self.assertEqual(403, resp_val) + self.assertEqual('application/xml', utils.content_type(resp)) + + def test_a_user_get_disabled_token(self): + utils.create_user(self.tenant, self.user, str(self.auth_token)) + resp, content = utils.user_get_json(self.tenant, + self.user, + str(self.disabled_token)) + resp_val = int(resp['status']) + utils.handle_user_resp(self, content, resp_val, + utils.content_type(resp)) + self.assertEqual(403, resp_val) + + def test_a_user_get_disabled_token_xml(self): + utils.create_user(self.tenant, self.user, str(self.auth_token)) + resp, content = utils.user_get_xml(self.tenant, + self.user, + str(self.disabled_token)) + resp_val = int(resp['status']) + utils.handle_user_resp(self, content, resp_val, + utils.content_type(resp)) + self.assertEqual(403, resp_val) + self.assertEqual('application/xml', utils.content_type(resp)) + + def test_a_user_get_missing_token(self): + utils.create_user(self.tenant, self.user, str(self.auth_token)) + resp, content = utils.user_get_json(self.tenant, + self.user, + str(self.missing_token)) + resp_val = int(resp['status']) + utils.handle_user_resp(self, content, resp_val, + utils.content_type(resp)) + self.assertEqual(401, resp_val) + + def test_a_user_get_missing_token_xml(self): + utils.create_user(self.tenant, self.user, str(self.auth_token)) + resp, content = utils.user_get_xml(self.tenant, self.user, + str(self.missing_token)) + resp_val = int(resp['status']) + utils.handle_user_resp(self, content, resp_val, + utils.content_type(resp)) + self.assertEqual(401, resp_val) + self.assertEqual('application/xml', utils.content_type(resp)) + + def test_a_user_get_invalid_token(self): + utils.create_user(self.tenant, self.user, str(self.auth_token)) + resp, content = utils.user_get_json(self.tenant, self.user, + str(self.invalid_token)) + resp_val = int(resp['status']) + utils.handle_user_resp(self, content, resp_val, + utils.content_type(resp)) + self.assertEqual(404, resp_val) + + def test_a_user_get_invalid_token_xml(self): + utils.create_user(self.tenant, self.user, str(self.auth_token)) + resp, content = utils.user_get_xml(self.tenant, self.user, + str(self.invalid_token)) + resp_val = int(resp['status']) + utils.handle_user_resp(self, content, resp_val, + utils.content_type(resp)) + self.assertEqual(404, resp_val) + self.assertEqual('application/xml', utils.content_type(resp)) + + def test_a_user_get_disabled_user(self): + utils.create_user(self.tenant, self.user, str(self.auth_token)) + resp, content = utils.user_get_json(self.tenant, + self.userdisabled, + str(self.auth_token)) + resp_val = int(resp['status']) + utils.handle_user_resp(self, content, resp_val, + utils.content_type(resp)) + self.assertEqual(403, resp_val) + + def test_a_user_get_disabled_user_xml(self): + utils.create_user(self.tenant, self.user, str(self.auth_token)) + resp, content = utils.user_get_xml(self.tenant, self.userdisabled, + str(self.auth_token)) + resp_val = int(resp['status']) + utils.handle_user_resp(self, content, resp_val, + utils.content_type(resp)) + self.assertEqual(403, resp_val) + self.assertEqual('application/xml', utils.content_type(resp)) + + def test_a_user_get_disabled_tenant(self): + utils.create_user(self.tenant, self.user, str(self.auth_token)) + resp, content = utils.user_get_json('0000', self.user, + str(self.auth_token)) + resp_val = int(resp['status']) + utils.handle_user_resp(self, content, resp_val, + utils.content_type(resp)) + self.assertEqual(403, resp_val) + + def test_a_user_get_disabled_tenant_xml(self): + utils.create_user(self.tenant, self.user, str(self.auth_token)) + resp, content = utils.user_get_xml('0000', self.user, + str(self.auth_token)) + resp_val = int(resp['status']) + utils.handle_user_resp(self, content, resp_val, + utils.content_type(resp)) + self.assertEqual(403, resp_val) + self.assertEqual('application/xml', + utils.content_type(resp)) + + +class DeleteUserTest(UserTest): + + def test_a_user_delete(self): + utils.create_user(self.tenant, self.user, + str(self.auth_token)) + resp = utils.delete_user(self.tenant, self.user, + str(self.auth_token)) + resp_val = int(resp['status']) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(204, resp_val) + + def test_a_user_delete_xml(self): + utils.create_user(self.tenant, self.user, + str(self.auth_token)) + resp = utils.delete_user_xml(self.tenant, self.user, + str(self.auth_token)) + resp_val = int(resp['status']) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(204, resp_val) + + def test_a_user_delete_expired_token(self): + utils.create_user(self.tenant, self.user, + str(self.auth_token)) + resp = utils.delete_user(self.tenant, self.user, + str(self.exp_auth_token)) + resp_val = int(resp['status']) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(403, resp_val) + + def test_a_user_delete_expired_token_xml(self): + utils.create_user(self.tenant, self.user, + str(self.auth_token)) + resp = utils.delete_user_xml(self.tenant, self.user, + str(self.exp_auth_token)) + resp_val = int(resp['status']) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(403, resp_val) + self.assertEqual('application/xml', utils.content_type(resp)) + + def test_a_user_delete_missing_token(self): + utils.create_user(self.tenant, self.user, + str(self.auth_token)) + resp = utils.delete_user(self.tenant, self.user, + str(self.missing_token)) + resp_val = int(resp['status']) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(401, resp_val) + + def test_a_user_delete_missing_token_xml(self): + utils.create_user(self.tenant, self.user, + str(self.auth_token)) + resp = utils.delete_user_xml(self.tenant, self.user, + str(self.missing_token)) + resp_val = int(resp['status']) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(401, resp_val) + self.assertEqual('application/xml', utils.content_type(resp)) + + def test_a_user_delete_invalid_token(self): + utils.create_user(self.tenant, self.user, + str(self.auth_token)) + resp = utils.delete_user(self.tenant, self.user, + str(self.invalid_token)) + resp_val = int(resp['status']) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(404, resp_val) + + def test_a_user_delete_invalid_token_xml(self): + utils.create_user(self.tenant, self.user, + str(self.auth_token)) + resp = utils.delete_user_xml(self.tenant, self.user, + str(self.invalid_token)) + resp_val = int(resp['status']) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(404, resp_val) + self.assertEqual('application/xml', utils.content_type(resp)) + + def test_a_user_delete_disabled_tenant(self): + utils.create_user(self.tenant, self.user, + str(self.auth_token)) + resp = utils.delete_user("0000", self.user, + str(self.auth_token)) + resp_val = int(resp['status']) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(403, resp_val) + + def test_a_user_delete_disabled_tenant_xml(self): + utils.create_user(self.tenant, self.user, + str(self.auth_token)) + resp = utils.delete_user_xml("0000", self.user, + str(self.auth_token)) + resp_val = int(resp['status']) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(403, resp_val) + self.assertEqual('application/xml', utils.content_type(resp)) + + +class GetUsersTest(UserTest): + + def test_users_get(self): + resp, content = utils.users_get_json(self.tenant, self.auth_token) + resp_val = int(resp['status']) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(200, resp_val) + + def test_users_get_xml(self): + resp, content = utils.users_get_xml(self.tenant, self.auth_token) + resp_val = int(resp['status']) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(200, resp_val) + self.assertEqual('application/xml', utils.content_type(resp)) + + def test_users_get_expired_token(self): + resp, content = utils.users_get_json(self.tenant, self.exp_auth_token) + resp_val = int(resp['status']) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(403, resp_val) + + def test_users_get_expired_token_xml(self): + resp, content = utils.users_get_xml(self.tenant, self.exp_auth_token) + resp_val = int(resp['status']) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(403, resp_val) + self.assertEqual('application/xml', utils.content_type(resp)) + + def test_users_get_disabled_token(self): + resp, content = utils.users_get_json(self.tenant, self.disabled_token) + resp_val = int(resp['status']) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(403, resp_val) + + def test_users_get_disabled_token_xml(self): + resp, content = utils.users_get_xml(self.tenant, self.disabled_token) + resp_val = int(resp['status']) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(403, resp_val) + self.assertEqual('application/xml', utils.content_type(resp)) + + def test_users_get_missing_token(self): + resp, content = utils.users_get_json(self.tenant, self.missing_token) + resp_val = int(resp['status']) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(401, resp_val) + + def test_users_get_missing_token_xml(self): + resp, content = utils.users_get_xml(self.tenant, self.missing_token) + resp_val = int(resp['status']) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(401, resp_val) + self.assertEqual('application/xml', utils.content_type(resp)) + + def test_users_get_invalid_token(self): + resp, content = utils.users_get_json(self.tenant, self.invalid_token) + resp_val = int(resp['status']) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(404, resp_val) + + def test_users_get_invalid_token_xml(self): + resp, content = utils.users_get_xml(self.tenant, self.invalid_token) + resp_val = int(resp['status']) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(404, resp_val) + self.assertEqual('application/xml', utils.content_type(resp)) + + def test_users_get_disabled_tenant(self): + resp, content = utils.users_get_json('0000', self.auth_token) + resp_val = int(resp['status']) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(403, resp_val) + + def test_users_get_disabled_tenant_xml(self): + resp, content = utils.users_get_xml('0000', self.auth_token) + resp_val = int(resp['status']) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(403, resp_val) + self.assertEqual('application/xml', utils.content_type(resp)) + + +class GetUsersGroupTest(UserTest): + + def test_users_group_get(self): + resp, content = utils.users_group_get_json(self.tenant, + self.user, + self.auth_token) + resp_val = int(resp['status']) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(200, resp_val) + + def test_users_group_get_xml(self): + resp, content = utils.users_group_get_xml(self.tenant, + self.user, + self.auth_token) + resp_val = int(resp['status']) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(200, resp_val) + self.assertEqual('application/xml', utils.content_type(resp)) + + def test_users_group_get_expired_token(self): + resp, content = utils.users_group_get_json(self.tenant, + self.user, + self.exp_auth_token) + resp_val = int(resp['status']) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(403, resp_val) + + def test_users_group_get_expired_token_xml(self): + resp, content = utils.users_group_get_xml(self.tenant, + self.user, + self.exp_auth_token) + resp_val = int(resp['status']) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(403, resp_val) + self.assertEqual('application/xml', utils.content_type(resp)) + + def test_users_group_get_disabled_token(self): + resp, content = utils.users_group_get_json(self.tenant, + self.user, + self.disabled_token) + resp_val = int(resp['status']) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(403, resp_val) + + def test_users_group_get_disabled_token_xml(self): + resp, content = utils.users_group_get_xml(self.tenant, + self.user, + self.disabled_token) + resp_val = int(resp['status']) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(403, resp_val) + self.assertEqual('application/xml', utils.content_type(resp)) + + def test_users_group_get_missing_token(self): + resp, content = utils.users_group_get_json(self.tenant, + self.user, + self.missing_token) + resp_val = int(resp['status']) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(401, resp_val) + + def test_users_group_get_missing_token_xml(self): + resp, content = utils.users_group_get_xml(self.tenant, + self.user, + self.missing_token) + resp_val = int(resp['status']) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(401, resp_val) + self.assertEqual('application/xml', utils.content_type(resp)) + + def test_users_group_get_invalid_token(self): + resp, content = utils.users_group_get_json(self.tenant, + self.user, + self.invalid_token) + resp_val = int(resp['status']) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(404, resp_val) + + def test_users_group_get_invalid_token_xml(self): + resp, content = utils.users_group_get_xml(self.tenant, + self.user, + self.invalid_token) + resp_val = int(resp['status']) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(404, resp_val) + self.assertEqual('application/xml', utils.content_type(resp)) + + def test_users_group_get_disabled_tenant(self): + resp, content = utils.users_group_get_json('0000', + self.user, + self.auth_token) + resp_val = int(resp['status']) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(403, resp_val) + + def test_users_group_get_disabled_tenant_xml(self): + resp, content = utils.users_group_get_xml('0000', + self.user, + self.auth_token) + resp_val = int(resp['status']) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(403, resp_val) + self.assertEqual('application/xml', utils.content_type(resp)) + + +class UpdateUserTest(UserTest): + + def test_user_update(self): + utils.create_user(self.tenant, self.user, str(self.auth_token)) + resp, content = utils.user_update_json(self.tenant, self.user, + self.auth_token) + resp_val = int(resp['status']) + content = json.loads(content) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + utils.delete_user(self.tenant, self.user, str(self.auth_token)) + self.assertEqual(200, resp_val) + self.assertEqual('updatedjoeuser@rackspace.com', + content['user']['email']) + + def test_user_update_xml(self): + utils.create_user(self.tenant, self.user, str(self.auth_token)) + resp, content = utils.user_update_xml(self.tenant, self.user, + self.auth_token) + resp_val = int(resp['status']) + content = etree.fromstring(content) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + utils.delete_user(self.tenant, self.user, str(self.auth_token)) + self.assertEqual(200, resp_val) + self.assertEqual('updatedjoeuser@rackspace.com', + content.get("email")) + self.assertEqual('application/xml', utils.content_type(resp)) + + def test_user_update_user_disabled(self): + utils.create_user(self.tenant, self.user, str(self.auth_token)) + resp, content = utils.user_update_json(self.tenant, + self.userdisabled, + self.auth_token) + resp_val = int(resp['status']) + content = json.loads(content) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(403, resp_val) + + def test_user_update_user_disabled_xml(self): + utils.create_user(self.tenant, self.user, str(self.auth_token)) + resp, content = utils.user_update_xml(self.tenant, + self.userdisabled, + self.auth_token) + resp_val = int(resp['status']) + content = etree.fromstring(content) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(403, resp_val) + self.assertEqual('application/xml', utils.content_type(resp)) + + def test_user_update_email_conflict(self): + utils.create_user(self.tenant, self.user, str(self.auth_token)) + resp, content = utils.user_update_json(self.tenant, + "joeuser", + self.auth_token, + "test_user@rackspace.com") + resp_val = int(resp['status']) + content = json.loads(content) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(409, resp_val) + + def test_user_update_email_conflict_xml(self): + utils.create_user(self.tenant, self.user, str(self.auth_token)) + resp, content = utils.user_update_xml(self.tenant, + "joeuser", + self.auth_token, + "test_user@rackspace.com") + resp_val = int(resp['status']) + content = etree.fromstring(content) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(409, resp_val) + self.assertEqual('application/xml', utils.content_type(resp)) + + def test_user_update_bad_request_json(self): + h = httplib2.Http(".cache") + resp, content = utils.create_user(self.tenant, self.user, + str(self.auth_token)) + url = '%stenants/%s/users/%s' % (URL, self.tenant, self.user) + data = '{"user_bad": { "bad": "updatedjoeuser@rackspace.com"}}' + resp, content = h.request(url, "PUT", body=data, + headers={"Content-Type": "application/json", + "X-Auth-Token": self.auth_token}) + resp_val = int(resp['status']) + content = json.loads(content) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + utils.delete_user(self.tenant, self.user, str(self.auth_token)) + self.assertEqual(400, resp_val) + + def test_user_update_bad_request_xml(self): + h = httplib2.Http(".cache") + resp, content = utils.create_user_xml(self.tenant, self.user, + str(self.auth_token)) + url = '%stenants/%s/users/%s' % (URL, self.tenant, self.user) + data = ' \ + user xmlns="http://docs.openstack.org/identity/api/v2.0" \ + email="updatedjoeuser@rackspace.com" />' + resp, content = h.request(url, "PUT", body=data, + headers={"Content-Type": "application/xml", + "X-Auth-Token": self.auth_token, + "ACCEPT": "application/xml"}) + resp_val = int(resp['status']) + content = etree.fromstring(content) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + utils.delete_user(self.tenant, self.user, str(self.auth_token)) + self.assertEqual(400, resp_val) + self.assertEqual('application/xml', utils.content_type(resp)) + + def test_user_update_expired_token(self): + utils.create_user(self.tenant, self.user, str(self.auth_token)) + resp, content = utils.user_update_json(self.tenant, + self.user, + self.exp_auth_token) + resp_val = int(resp['status']) + content = json.loads(content) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(403, resp_val) + + def test_user_update_expired_token_xml(self): + utils.create_user(self.tenant, self.user, str(self.auth_token)) + resp, content = utils.user_update_xml(self.tenant, + self.user, + self.exp_auth_token) + resp_val = int(resp['status']) + content = etree.fromstring(content) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(403, resp_val) + self.assertEqual('application/xml', utils.content_type(resp)) + + def test_user_update_disabled_token(self): + utils.create_user(self.tenant, self.user, str(self.auth_token)) + resp, content = utils.user_update_json(self.tenant, + self.user, + self.disabled_token) + resp_val = int(resp['status']) + content = json.loads(content) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(403, resp_val) + + def test_user_update_disabled_token_xml(self): + utils.create_user(self.tenant, self.user, str(self.auth_token)) + resp, content = utils.user_update_xml(self.tenant, + self.user, + self.disabled_token) + resp_val = int(resp['status']) + content = etree.fromstring(content) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(403, resp_val) + self.assertEqual('application/xml', utils.content_type(resp)) + + def test_user_update_invalid_token(self): + utils.create_user(self.tenant, self.user, str(self.auth_token)) + resp, content = utils.user_update_json(self.tenant, + self.user, + self.invalid_token) + resp_val = int(resp['status']) + content = json.loads(content) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(404, resp_val) + + def test_user_update_invalid_token_xml(self): + utils.create_user(self.tenant, self.user, str(self.auth_token)) + resp, content = utils.user_update_xml(self.tenant, + self.user, + self.invalid_token) + resp_val = int(resp['status']) + content = etree.fromstring(content) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(404, resp_val) + self.assertEqual('application/xml', utils.content_type(resp)) + + def test_user_update_missing_token(self): + utils.create_user(self.tenant, self.user, str(self.auth_token)) + resp, content = utils.user_update_json(self.tenant, + self.user, + self.missing_token) + resp_val = int(resp['status']) + content = json.loads(content) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(401, resp_val) + + def test_user_update_missing_token_xml(self): + utils.create_user(self.tenant, self.user, str(self.auth_token)) + resp, content = utils.user_update_xml(self.tenant, + self.user, + self.missing_token) + resp_val = int(resp['status']) + content = etree.fromstring(content) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(401, resp_val) + self.assertEqual('application/xml', utils.content_type(resp)) + + +class SetPasswordTest(UserTest): + + def test_user_password(self): + utils.create_user(self.tenant, self.user, str(self.auth_token)) + resp, content = utils.user_password_json(self.tenant, + self.user, + str(self.auth_token)) + resp_val = int(resp['status']) + content = json.loads(content) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + utils.delete_user(self.tenant, self.user, str(self.auth_token)) + self.assertEqual(200, resp_val) + self.assertEqual('p@ssword', content['user']['password']) + + def test_user_password_xml(self): + utils.create_user(self.tenant, self.user, str(self.auth_token)) + resp, content = utils.user_password_xml(self.tenant, + self.user, + str(self.auth_token)) + resp_val = int(resp['status']) + content = etree.fromstring(content) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + utils.delete_user(self.tenant, self.user, str(self.auth_token)) + self.assertEqual(200, resp_val) + self.assertEqual('p@ssword', content.get("password")) + self.assertEqual('application/xml', utils.content_type(resp)) + + def test_user_password_user_disabled(self): + utils.create_user(self.tenant, self.user, str(self.auth_token)) + resp, content = utils.user_password_json(self.tenant, + self.userdisabled, + str(self.auth_token)) + resp_val = int(resp['status']) + content = json.loads(content) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(403, resp_val) + + def test_user_password_user_disabled_xml(self): + utils.create_user(self.tenant, self.user, str(self.auth_token)) + resp, content = utils.user_password_xml(self.tenant, + self.userdisabled, + str(self.auth_token)) + resp_val = int(resp['status']) + content = etree.fromstring(content) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(403, resp_val) + self.assertEqual('application/xml', utils.content_type(resp)) + + def test_user_password_bad_request_json(self): + h = httplib2.Http(".cache") + utils.create_user(self.tenant, self.user, + str(self.auth_token)) + url = '%stenants/%s/users/%s/password' % (URL, self.tenant, self.user) + data = '{"user_bad": { "password": "p@ssword"}}' + resp, content = h.request(url, "PUT", body=data, + headers={"Content-Type": "application/json", + "X-Auth-Token": self.auth_token}) + resp_val = int(resp['status']) + content = json.loads(content) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + utils.delete_user(self.tenant, self.user, str(self.auth_token)) + self.assertEqual(400, resp_val) + + def test_user_password_bad_request_xml(self): + h = httplib2.Http(".cache") + utils.create_user_xml(self.tenant, self.user, str(self.auth_token)) + url = '%stenants/%s/users/%s/password' % (URL, self.tenant, self.user) + data = ' \ + user xmlns="http://docs.openstack.org/identity/api/v2.0" \ + password="p@ssword" />' + resp, content = h.request(url, "PUT", body=data, + headers={"Content-Type": "application/xml", + "X-Auth-Token": self.auth_token, + "ACCEPT": "application/xml"}) + resp_val = int(resp['status']) + content = etree.fromstring(content) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + utils.delete_user(self.tenant, self.user, str(self.auth_token)) + self.assertEqual(400, resp_val) + self.assertEqual('application/xml', utils.content_type(resp)) + + def test_user_password_expired_token(self): + utils.create_user(self.tenant, self.user, str(self.auth_token)) + resp, content = utils.user_password_json(self.tenant, + self.user, + str(self.exp_auth_token)) + resp_val = int(resp['status']) + content = json.loads(content) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(403, resp_val) + + def test_user_password_expired_token_xml(self): + utils.create_user(self.tenant, self.user, str(self.auth_token)) + resp, content = utils.user_password_xml(self.tenant, + self.user, + str(self.exp_auth_token)) + resp_val = int(resp['status']) + content = etree.fromstring(content) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(403, resp_val) + self.assertEqual('application/xml', utils.content_type(resp)) + + def test_user_password_disabled_token(self): + utils.create_user(self.tenant, self.user, str(self.auth_token)) + resp, content = utils.user_password_json(self.tenant, + self.user, + str(self.disabled_token)) + resp_val = int(resp['status']) + content = json.loads(content) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(403, resp_val) + + def test_user_password_disabled_token_xml(self): + utils.create_user(self.tenant, self.user, str(self.auth_token)) + resp, content = utils.user_password_xml(self.tenant, + self.user, + str(self.disabled_token)) + resp_val = int(resp['status']) + content = etree.fromstring(content) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(403, resp_val) + self.assertEqual('application/xml', utils.content_type(resp)) + + def test_user_password_invalid_token(self): + utils.create_user(self.tenant, + self.user, + str(self.auth_token)) + resp, content = utils.user_password_json(self.tenant, + self.user, + str(self.invalid_token)) + resp_val = int(resp['status']) + content = json.loads(content) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(404, resp_val) + + def test_user_password_invalid_token_xml(self): + utils.create_user(self.tenant, self.user, str(self.auth_token)) + resp, content = utils.user_password_xml(self.tenant, + self.user, + str(self.invalid_token)) + resp_val = int(resp['status']) + content = etree.fromstring(content) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(404, resp_val) + self.assertEqual('application/xml', utils.content_type(resp)) + + def test_user_password_missing_token(self): + utils.create_user(self.tenant, self.user, str(self.auth_token)) + resp, content = utils.user_password_json(self.tenant, + self.user, + str(self.missing_token)) + resp_val = int(resp['status']) + content = json.loads(content) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(401, resp_val) + + def test_user_password_missing_token_xml(self): + utils.create_user(self.tenant, self.user, str(self.auth_token)) + resp, content = utils.user_password_xml(self.tenant, + self.user, + str(self.missing_token)) + resp_val = int(resp['status']) + content = etree.fromstring(content) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(401, resp_val) + self.assertEqual('application/xml', utils.content_type(resp)) + + +class SetEnabledTest(UserTest): + + def test_user_enabled(self): + utils.create_user(self.tenant, self.user, str(self.auth_token)) + resp, content = utils.user_enabled_json(self.tenant, + self.user, + str(self.auth_token)) + resp_val = int(resp['status']) + content = json.loads(content) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + utils.delete_user(self.tenant, self.user, str(self.auth_token)) + self.assertEqual(200, resp_val) + self.assertEqual(True, content['user']['enabled']) + + def test_user_enabled_xml(self): + utils.create_user(self.tenant, self.user, str(self.auth_token)) + resp, content = utils.user_enabled_xml(self.tenant, + self.user, + str(self.auth_token)) + resp_val = int(resp['status']) + content = etree.fromstring(content) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + utils.delete_user(self.tenant, self.user, str(self.auth_token)) + self.assertEqual(200, resp_val) + self.assertEqual('true', content.get("enabled")) + self.assertEqual('application/xml', utils.content_type(resp)) + + def test_user_enabled_bad_request_json(self): + h = httplib2.Http(".cache") + utils.create_user(self.tenant, self.user, + str(self.auth_token)) + url = '%stenants/%s/users/%s/enabled' % (URL, self.tenant, self.user) + data = '{"user_bad": { "enabled": true}}' + resp, content = h.request(url, "PUT", body=data, + headers={"Content-Type": "application/json", + "X-Auth-Token": self.auth_token}) + resp_val = int(resp['status']) + content = json.loads(content) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + utils.delete_user(self.tenant, self.user, str(self.auth_token)) + self.assertEqual(400, resp_val) + + def test_user_enabled_bad_request_xml(self): + h = httplib2.Http(".cache") + utils.create_user_xml(self.tenant, self.user, + str(self.auth_token)) + url = '%stenants/%s/users/%s/enabled' % (URL, self.tenant, self.user) + data = ' \ + user xmlns="http://docs.openstack.org/identity/api/v2.0" \ + enabled="true" />' + resp, content = h.request(url, "PUT", body=data, + headers={"Content-Type": "application/xml", + "X-Auth-Token": self.auth_token, + "ACCEPT": "application/xml"}) + resp_val = int(resp['status']) + content = etree.fromstring(content) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + utils.delete_user(self.tenant, self.user, str(self.auth_token)) + self.assertEqual(400, resp_val) + self.assertEqual('application/xml', utils.content_type(resp)) + + def test_user_enabled_disabled_tenant(self): + utils.create_user(self.tenant, self.user, str(self.auth_token)) + resp, content = utils.user_enabled_json('0000', + self.user, + str(self.auth_token)) + resp_val = int(resp['status']) + content = json.loads(content) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(403, resp_val) + + def test_user_enabled_disabled_tenant_xml(self): + utils.create_user(self.tenant, self.user, str(self.auth_token)) + resp, content = utils.user_enabled_xml('0000', + self.user, + str(self.auth_token)) + resp_val = int(resp['status']) + content = etree.fromstring(content) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(403, resp_val) + self.assertEqual('application/xml', utils.content_type(resp)) + + def test_user_enabled_expired_token(self): + utils.create_user(self.tenant, self.user, str(self.auth_token)) + resp, content = utils.user_enabled_json(self.tenant, + self.user, + str(self.exp_auth_token)) + resp_val = int(resp['status']) + content = json.loads(content) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(403, resp_val) + + def test_user_enabled_expired_token_xml(self): + utils.create_user(self.tenant, self.user, str(self.auth_token)) + resp, content = utils.user_enabled_xml(self.tenant, + self.user, + str(self.exp_auth_token)) + resp_val = int(resp['status']) + content = etree.fromstring(content) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(403, resp_val) + self.assertEqual('application/xml', utils.content_type(resp)) + + def test_user_enabled_disabled_token(self): + utils.create_user(self.tenant, self.user, str(self.auth_token)) + resp, content = utils.user_enabled_json(self.tenant, + self.user, + str(self.disabled_token)) + resp_val = int(resp['status']) + content = json.loads(content) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(403, resp_val) + + def test_user_enabled_disabled_token_xml(self): + utils.create_user(self.tenant, self.user, str(self.auth_token)) + resp, content = utils.user_enabled_xml(self.tenant, + self.user, + str(self.disabled_token)) + resp_val = int(resp['status']) + content = etree.fromstring(content) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(403, resp_val) + self.assertEqual('application/xml', utils.content_type(resp)) + + def test_user_enabled_invalid_token(self): + utils.create_user(self.tenant, self.user, str(self.auth_token)) + resp, content = utils.user_enabled_json(self.tenant, + self.user, + str(self.invalid_token)) + resp_val = int(resp['status']) + content = json.loads(content) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(404, resp_val) + + def test_user_enabled_invalid_token_xml(self): + utils.create_user(self.tenant, self.user, str(self.auth_token)) + resp, content = utils.user_enabled_xml(self.tenant, + self.user, + str(self.invalid_token)) + resp_val = int(resp['status']) + content = etree.fromstring(content) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(404, resp_val) + self.assertEqual('application/xml', utils.content_type(resp)) + + def test_user_enabled_missing_token(self): + utils.create_user(self.tenant, self.user, str(self.auth_token)) + resp, content = utils.user_enabled_json(self.tenant, + self.user, + str(self.missing_token)) + resp_val = int(resp['status']) + content = json.loads(content) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(401, resp_val) + + def test_user_enabled_missing_token_xml(self): + utils.create_user(self.tenant, self.user, str(self.auth_token)) + resp, content = utils.user_enabled_xml(self.tenant, + self.user, + str(self.missing_token)) + resp_val = int(resp['status']) + content = etree.fromstring(content) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(401, resp_val) + self.assertEqual('application/xml', utils.content_type(resp)) + + +class AddUserTest(UserTest): + + def setUp(self): + self.token = utils.get_token('joeuser1', 'secrete', '1234') + self.tenant = utils.get_another_tenant() + self.password = utils.get_password() + self.email = utils.get_email() + self.user = 'joeuser1' + self.userdisabled = utils.get_userdisabled() + self.auth_token = utils.get_auth_token() + self.exp_auth_token = utils.get_exp_auth_token() + self.disabled_token = utils.get_disabled_token() + self.missing_token = utils.get_none_token() + self.invalid_token = utils.get_non_existing_token() + + def tearDown(self): + utils.delete_user(self.tenant, self.user, str(self.auth_token)) + utils.delete_tenant(self.tenant, str(self.auth_token)) + + def test_add_user_tenant(self): + utils.create_tenant(self.tenant, str(self.auth_token)) + resp, content = utils.create_user(self.tenant, + self.user, + str(self.auth_token)) + resp_val = int(resp['status']) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(201, resp_val) + + def test_add_user_tenant_xml(self): + utils.create_tenant(self.tenant, str(self.auth_token)) + resp, content = utils.create_user_xml(self.tenant, + self.user, + str(self.auth_token)) + resp_val = int(resp['status']) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(201, resp_val) + + def test_add_user_tenant_conflict(self): + utils.create_tenant(self.tenant, str(self.auth_token)) + utils.create_user(self.tenant, self.user, str(self.auth_token)) + resp, content = utils.create_user(self.tenant, + self.user, + str(self.auth_token)) + + resp_val = int(resp['status']) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(409, resp_val) + + def test_add_user_tenant_conflict_xml(self): + utils.create_tenant(self.tenant, str(self.auth_token)) + utils.create_user_xml(self.tenant, self.user, str(self.auth_token)) + resp, content = utils.create_user_xml(self.tenant, + self.user, + str(self.auth_token)) + resp_val = int(resp['status']) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(409, resp_val) + + + def test_add_user_tenant_expired_token(self): + utils.create_tenant(self.tenant, str(self.auth_token)) + resp, content = utils.create_user(self.tenant, + self.user, + str(self.exp_auth_token)) + resp_val = int(resp['status']) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(403, resp_val) + + def test_add_user_tenant_expired_token_xml(self): + utils.create_tenant(self.tenant, str(self.auth_token)) + resp, content = utils.create_user_xml(self.tenant, + self.user, + str(self.exp_auth_token)) + resp_val = int(resp['status']) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(403, resp_val) + + def test_add_user_tenant_disabled_token(self): + utils.create_tenant(self.tenant, str(self.auth_token)) + resp, content = utils.create_user(self.tenant, + self.user, + str(self.disabled_token)) + resp_val = int(resp['status']) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(403, resp_val) + + def test_add_user_tenant_disabled_token_xml(self): + utils.create_tenant(self.tenant, str(self.auth_token)) + resp, content = utils.create_user_xml(self.tenant, + self.user, + str(self.disabled_token)) + resp_val = int(resp['status']) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(403, resp_val) + + def test_add_user_tenant_invalid_token(self): + utils.create_tenant(self.tenant, str(self.auth_token)) + resp, content = utils.create_user(self.tenant, + self.user, + str(self.invalid_token)) + resp_val = int(resp['status']) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(404, resp_val) + + def test_add_user_tenant_invalid_token_xml(self): + utils.create_tenant(self.tenant, str(self.auth_token)) + resp, content = utils.create_user_xml(self.tenant, + self.user, + str(self.invalid_token)) + resp_val = int(resp['status']) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(404, resp_val) + + def test_add_user_tenant_missing_token(self): + utils.create_tenant(self.tenant, str(self.auth_token)) + resp, content = utils.create_user(self.tenant, + self.user, + str(self.missing_token)) + resp_val = int(resp['status']) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(401, resp_val) + + def test_add_user_tenant_missing_token_xml(self): + utils.create_tenant(self.tenant, str(self.auth_token)) + resp, content = utils.create_user_xml(self.tenant, + self.user, + str(self.missing_token)) + resp_val = int(resp['status']) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(401, resp_val) + + def test_add_user_tenant_disabled_tenant(self): + utils.create_tenant(self.tenant, str(self.auth_token)) + resp, content = utils.create_user('0000', + self.user, + str(self.auth_token)) + resp_val = int(resp['status']) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(403, resp_val) + + def test_add_user_tenant_disabled_tenant_xml(self): + utils.create_tenant(self.tenant, str(self.auth_token)) + resp, content = utils.create_user_xml('0000', + self.user, + str(self.auth_token)) + resp_val = int(resp['status']) + if resp_val == 500: + self.fail('Identity Fault') + elif resp_val == 503: + self.fail('Service Not Available') + self.assertEqual(403, resp_val) + +if __name__ == '__main__': + unittest.main() diff --git a/keystone/test/unit/test_version.py b/keystone/test/unit/test_version.py new file mode 100644 index 00000000..3e98935e --- /dev/null +++ b/keystone/test/unit/test_version.py @@ -0,0 +1,49 @@ +# vim: tabstop=4 shiftwidth=4 softtabstop=4 +# Copyright (c) 2010-2011 OpenStack, LLC. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or +# implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +import httplib2 +import os +import sys +sys.path.append(os.path.abspath(os.path.join(os.path.abspath(__file__), + '..', '..', '..', '..', 'keystone'))) +import unittest + +import test_common as utils + + +class VersionTest(unittest.TestCase): + + #Given _a_ to make inherited test cases in an order. + #here to call below method will call as last test case + + def test_a_get_version_json(self): + header = httplib2.Http(".cache") + resp, content = header.request(utils.URL, "GET", body="", + headers={"Content-Type": "application/json"}) + self.assertEqual(200, int(resp['status'])) + self.assertEqual('application/json', utils.content_type(resp)) + + def test_a_get_version_xml(self): + header = httplib2.Http(".cache") + resp, content = header.request(utils.URL, "GET", body="", + headers={"Content-Type": "application/xml", + "ACCEPT": "application/xml"}) + self.assertEqual(200, int(resp['status'])) + self.assertEqual('application/xml', utils.content_type(resp)) + +if __name__ == '__main__': + unittest.main() -- cgit From ef2033be3411ade4e43225de0995fa27baa378fc Mon Sep 17 00:00:00 2001 From: Ziad Sawalha Date: Sat, 11 Jun 2011 16:09:04 -0500 Subject: Setup.py fix --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index 2c54da52..1ddf18eb 100644 --- a/setup.py +++ b/setup.py @@ -37,7 +37,7 @@ setup( entry_points={ 'paste.app_factory': ['main=identity:app_factory'], 'paste.filter_factory': [ - 'remoteauth=keystone:remoteauth_factory', + 'remoteauth=keystone.middleware.remoteauth:remoteauth_factory', 'tokenauth=keystone.auth_protocols.auth_token:filter_factory', ], }, -- cgit