summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--etc/keystone.conf.sample6
-rw-r--r--keystone/assignment/backends/ldap.py12
-rw-r--r--keystone/common/config.py2
-rw-r--r--keystone/common/sql/core.py11
-rw-r--r--keystone/common/wsgi.py2
-rw-r--r--keystone/exception.py128
-rw-r--r--keystone/identity/backends/kvs.py2
-rw-r--r--keystone/identity/backends/ldap.py297
-rw-r--r--keystone/identity/backends/pam.py2
-rw-r--r--keystone/identity/backends/sql.py2
-rw-r--r--keystone/identity/core.py2
-rw-r--r--keystone/test.py3
-rw-r--r--keystone/token/provider.py4
-rw-r--r--tests/_ldap_livetest.py3
-rw-r--r--tests/test_backend_kvs.py22
-rw-r--r--tests/test_backend_ldap.py74
-rw-r--r--tests/test_content_types.py3
-rw-r--r--tests/test_exception.py32
-rw-r--r--tests/test_keystoneclient.py18
-rw-r--r--tests/test_keystoneclient_sql.py4
-rw-r--r--tests/test_pki_token_provider.conf3
-rw-r--r--tests/test_sql_core.py8
-rw-r--r--tests/test_token_provider.py9
-rw-r--r--tests/test_uuid_token_provider.conf3
-rw-r--r--tests/test_v3_auth.py4
-rw-r--r--tests/test_wsgi.py5
26 files changed, 181 insertions, 480 deletions
diff --git a/etc/keystone.conf.sample b/etc/keystone.conf.sample
index 4c0327cf..a49a9a5e 100644
--- a/etc/keystone.conf.sample
+++ b/etc/keystone.conf.sample
@@ -128,7 +128,8 @@
# driver = keystone.token.backends.sql.Token
# Controls the token construction, validation, and revocation operations.
-# provider = keystone.token.providers.pki.Provider
+# Core providers are keystone.token.providers.[pki|uuid].Provider
+# provider =
# Amount of time a token should remain valid (in seconds)
# expiration = 86400
@@ -165,7 +166,8 @@
[signing]
# Deprecated in favor of provider in the [token] section
-#token_format = PKI
+# Allowed values are PKI or UUID
+#token_format =
#certfile = /etc/keystone/pki/certs/signing_cert.pem
#keyfile = /etc/keystone/pki/private/signing_key.pem
diff --git a/keystone/assignment/backends/ldap.py b/keystone/assignment/backends/ldap.py
index b1b3f99f..f8c81eae 100644
--- a/keystone/assignment/backends/ldap.py
+++ b/keystone/assignment/backends/ldap.py
@@ -55,20 +55,8 @@ class Assignment(assignment.Driver):
self.project = ProjectApi(CONF)
self.role = RoleApi(CONF)
-
self._identity_api = None
- @property
- def identity_api(self):
- return self._identity_api
-
- @identity_api.setter
- def identity_api(self, value):
- self._identity_api = value
- #TODO(ayoung): only left here to prevent unit test from breaking
- #once we remove here. the getter and setter can be removed as well.
- self._identity_api.driver.project = self.project
-
def get_project(self, tenant_id):
return self._set_default_domain(self.project.get(tenant_id))
diff --git a/keystone/common/config.py b/keystone/common/config.py
index b0a534f8..10c47a35 100644
--- a/keystone/common/config.py
+++ b/keystone/common/config.py
@@ -240,7 +240,7 @@ def configure():
# signing
register_str(
- 'token_format', group='signing', default="PKI")
+ 'token_format', group='signing', default=None)
register_str(
'certfile',
group='signing',
diff --git a/keystone/common/sql/core.py b/keystone/common/sql/core.py
index 7978fcc5..2d3114f2 100644
--- a/keystone/common/sql/core.py
+++ b/keystone/common/sql/core.py
@@ -243,9 +243,10 @@ class Base(object):
def get_session(self, autocommit=True, expire_on_commit=False):
"""Return a SQLAlchemy session."""
- self._engine = self._engine or self.get_engine()
- self._sessionmaker = self._sessionmaker or self.get_sessionmaker(
- self._engine)
+ if not self._engine:
+ self._engine = self.get_engine()
+ self._sessionmaker = self.get_sessionmaker(self._engine)
+ register_global_engine_callback(self.clear_engine)
return self._sessionmaker(autocommit=autocommit,
expire_on_commit=expire_on_commit)
@@ -300,6 +301,10 @@ class Base(object):
autocommit=autocommit,
expire_on_commit=expire_on_commit)
+ def clear_engine(self):
+ self._engine = None
+ self._sessionmaker = None
+
def handle_conflicts(type='object'):
"""Converts IntegrityError into HTTP 409 Conflict."""
diff --git a/keystone/common/wsgi.py b/keystone/common/wsgi.py
index c7e30576..381f1ff0 100644
--- a/keystone/common/wsgi.py
+++ b/keystone/common/wsgi.py
@@ -583,7 +583,7 @@ def render_exception(error):
body = {'error': {
'code': error.code,
'title': error.title,
- 'message': str(error)
+ 'message': unicode(error)
}}
if isinstance(error, exception.AuthPluginException):
body['error']['identity'] = error.authentication
diff --git a/keystone/exception.py b/keystone/exception.py
index db5f5005..5e1defba 100644
--- a/keystone/exception.py
+++ b/keystone/exception.py
@@ -13,10 +13,10 @@
# 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 re
from keystone.common import config
from keystone.common import logging
+from keystone.openstack.common.gettextutils import _ # noqa
CONF = config.CONF
@@ -29,15 +29,15 @@ _FATAL_EXCEPTION_FORMAT_ERRORS = False
class Error(StandardError):
"""Base error class.
- Child classes should define an HTTP status code, title, and a doc string.
+ Child classes should define an HTTP status code, title, and a
+ message_format.
"""
code = None
title = None
+ message_format = None
def __init__(self, message=None, **kwargs):
- """Use the doc string as the error message by default."""
-
try:
message = self._build_message(message, **kwargs)
except KeyError:
@@ -45,8 +45,8 @@ class Error(StandardError):
if _FATAL_EXCEPTION_FORMAT_ERRORS:
raise
else:
- LOG.warning('missing exception kwargs (programmer error)')
- message = self.__doc__
+ LOG.warning(_('missing exception kwargs (programmer error)'))
+ message = self.message_format
super(Error, self).__init__(message)
@@ -57,42 +57,31 @@ class Error(StandardError):
"""
if not message:
- message = re.sub('[ \n]+', ' ', self.__doc__ % kwargs)
- message = message.strip()
+ message = self.message_format % kwargs
return message
class ValidationError(Error):
- """Expecting to find %(attribute)s in %(target)s.
-
- The server could not comply with the request since it is either malformed
- or otherwise incorrect.
-
- The client is assumed to be in error.
-
- """
+ message_format = _("Expecting to find %(attribute)s in %(target)s."
+ " The server could not comply with the request"
+ " since it is either malformed or otherwise"
+ " incorrect. The client is assumed to be in error.")
code = 400
title = 'Bad Request'
class StringLengthExceeded(ValidationError):
- """String length exceeded.
-
- The length of string "%(string)s" exceeded the limit of column
- %(type)s(CHAR(%(length)d)).
-
- """
+ message_format = _("String length exceeded.The length of"
+ " string '%(string)s' exceeded the limit"
+ " of column %(type)s(CHAR(%(length)d)).")
class ValidationSizeError(Error):
- """Request attribute %(attribute)s must be less than or equal to %(size)i.
-
- The server could not comply with the request because the attribute
- size is invalid (too large).
-
- The client is assumed to be in error.
-
- """
+ message_format = _("Request attribute %(attribute)s must be"
+ " less than or equal to %(size)i. The server"
+ " could not comply with the request because"
+ " the attribute size is invalid (too large)."
+ " The client is assumed to be in error.")
code = 400
title = 'Bad Request'
@@ -103,19 +92,19 @@ class SecurityError(Error):
def _build_message(self, message, **kwargs):
"""Only returns detailed messages in debug mode."""
if CONF.debug:
- return message or self.__doc__ % kwargs
+ return message or self.message_format % kwargs
else:
- return self.__doc__ % kwargs
+ return self.message_format % kwargs
class Unauthorized(SecurityError):
- """The request you have made requires authentication."""
+ message_format = _("The request you have made requires authentication.")
code = 401
title = 'Unauthorized'
class AuthPluginException(Unauthorized):
- """Authentication plugin error."""
+ message_format = _("Authentication plugin error.")
def __init__(self, *args, **kwargs):
super(AuthPluginException, self).__init__(*args, **kwargs)
@@ -123,7 +112,7 @@ class AuthPluginException(Unauthorized):
class AuthMethodNotSupported(AuthPluginException):
- """Attempted to authenticate with an unsupported method."""
+ message_format = _("Attempted to authenticate with an unsupported method.")
def __init__(self, *args, **kwargs):
super(AuthMethodNotSupported, self).__init__(*args, **kwargs)
@@ -131,7 +120,7 @@ class AuthMethodNotSupported(AuthPluginException):
class AdditionalAuthRequired(AuthPluginException):
- """Additional authentications steps required."""
+ message_format = _("Additional authentications steps required.")
def __init__(self, auth_response=None, **kwargs):
super(AdditionalAuthRequired, self).__init__(message=None, **kwargs)
@@ -139,112 +128,111 @@ class AdditionalAuthRequired(AuthPluginException):
class Forbidden(SecurityError):
- """You are not authorized to perform the requested action."""
+ message_format = _("You are not authorized to perform the"
+ " requested action.")
code = 403
title = 'Forbidden'
class ForbiddenAction(Forbidden):
- """You are not authorized to perform the requested action, %(action)s."""
+ message_format = _("You are not authorized to perform the"
+ " requested action, %(action)s.")
class NotFound(Error):
- """Could not find, %(target)s."""
+ message_format = _("Could not find, %(target)s.")
code = 404
title = 'Not Found'
class EndpointNotFound(NotFound):
- """Could not find endpoint, %(endpoint_id)s."""
+ message_format = _("Could not find endpoint, %(endpoint_id)s.")
class MetadataNotFound(NotFound):
- """An unhandled exception has occurred: Could not find metadata."""
- # (dolph): metadata is not a user-facing concept,
- # so this exception should not be exposed
+ """(dolph): metadata is not a user-facing concept,
+ so this exception should not be exposed
+ """
+ message_format = _("An unhandled exception has occurred:"
+ " Could not find metadata.")
class PolicyNotFound(NotFound):
- """Could not find policy, %(policy_id)s."""
+ message_format = _("Could not find policy, %(policy_id)s.")
class RoleNotFound(NotFound):
- """Could not find role, %(role_id)s."""
+ message_format = _("Could not find role, %(role_id)s.")
class ServiceNotFound(NotFound):
- """Could not find service, %(service_id)s."""
+ message_format = _("Could not find service, %(service_id)s.")
class DomainNotFound(NotFound):
- """Could not find domain, %(domain_id)s."""
+ message_format = _("Could not find domain, %(domain_id)s.")
class ProjectNotFound(NotFound):
- """Could not find project, %(project_id)s."""
+ message_format = _("Could not find project, %(project_id)s.")
class TokenNotFound(NotFound):
- """Could not find token, %(token_id)s."""
+ message_format = _("Could not find token, %(token_id)s.")
class UserNotFound(NotFound):
- """Could not find user, %(user_id)s."""
+ message_format = _("Could not find user, %(user_id)s.")
class GroupNotFound(NotFound):
- """Could not find group, %(group_id)s."""
+ message_format = _("Could not find group, %(group_id)s.")
class TrustNotFound(NotFound):
- """Could not find trust, %(trust_id)s."""
+ message_format = _("Could not find trust, %(trust_id)s.")
class CredentialNotFound(NotFound):
- """Could not find credential, %(credential_id)s."""
+ message_format = _("Could not find credential, %(credential_id)s.")
class VersionNotFound(NotFound):
- """Could not find version, %(version)s."""
+ message_format = _("Could not find version, %(version)s.")
class Conflict(Error):
- """Conflict occurred attempting to store %(type)s.
-
- %(details)s
-
- """
+ message_format = _("Conflict occurred attempting to store %(type)s."
+ " %(details)s")
code = 409
title = 'Conflict'
class RequestTooLarge(Error):
- """Request is too large."""
+ message_format = _("Request is too large.")
code = 413
title = 'Request is too large.'
class UnexpectedError(Error):
- """An unexpected error prevented the server from fulfilling your request.
-
- %(exception)s
-
- """
+ message_format = _("An unexpected error prevented the server"
+ " from fulfilling your request. %(exception)s")
code = 500
title = 'Internal Server Error'
class MalformedEndpoint(UnexpectedError):
- """Malformed endpoint URL (%(endpoint)s), see ERROR log for details."""
+ message_format = _("Malformed endpoint URL (%(endpoint)s),"
+ " see ERROR log for details.")
class NotImplemented(Error):
- """The action you have requested has not been implemented."""
+ message_format = _("The action you have requested has not"
+ " been implemented.")
code = 501
title = 'Not Implemented'
class PasteConfigNotFound(UnexpectedError):
- """The Keystone paste configuration file %(config_file)s could not be
- found.
- """
+ message_format = _("The Keystone paste configuration file"
+ " %(config_file)s could not be found.")
diff --git a/keystone/identity/backends/kvs.py b/keystone/identity/backends/kvs.py
index 83535108..0323d3d0 100644
--- a/keystone/identity/backends/kvs.py
+++ b/keystone/identity/backends/kvs.py
@@ -28,7 +28,7 @@ class Identity(kvs.Base, identity.Driver):
return "keystone.assignment.backends.kvs.Assignment"
# Public interface
- def authenticate(self, user_id=None, password=None):
+ def authenticate(self, user_id, password):
user_ref = None
try:
user_ref = self._get_user(user_id)
diff --git a/keystone/identity/backends/ldap.py b/keystone/identity/backends/ldap.py
index 1bdec3a3..f9e546a9 100644
--- a/keystone/identity/backends/ldap.py
+++ b/keystone/identity/backends/ldap.py
@@ -41,11 +41,6 @@ DEFAULT_DOMAIN = {
class Identity(identity.Driver):
def __init__(self):
super(Identity, self).__init__()
- self.LDAP_URL = CONF.ldap.url
- self.LDAP_USER = CONF.ldap.user
- self.LDAP_PASSWORD = CONF.ldap.password
- self.suffix = CONF.ldap.suffix
-
self.user = UserApi(CONF)
self.group = GroupApi(CONF)
@@ -57,10 +52,7 @@ class Identity(identity.Driver):
def create_project(self, project_id, project):
return self.assignment_api.create_project(project_id, project)
- def get_project(self, project_id):
- return self.assignment_api.get_project(project_id)
-
- def authenticate(self, user_id=None, password=None):
+ def authenticate(self, user_id, password):
try:
user_ref = self._get_user(user_id)
except exception.UserNotFound:
@@ -273,293 +265,6 @@ class UserApi(common_ldap.EnabledEmuMixIn, common_ldap.BaseLdap):
return identity.filter_user(user)
-# TODO(termie): turn this into a data object and move logic to driver
-class ProjectApi(common_ldap.EnabledEmuMixIn, common_ldap.BaseLdap):
- DEFAULT_OU = 'ou=Projects'
- DEFAULT_STRUCTURAL_CLASSES = []
- DEFAULT_OBJECTCLASS = 'groupOfNames'
- DEFAULT_ID_ATTR = 'cn'
- DEFAULT_MEMBER_ATTRIBUTE = 'member'
- DEFAULT_ATTRIBUTE_IGNORE = []
- NotFound = exception.ProjectNotFound
- notfound_arg = 'project_id' # NOTE(yorik-sar): while options_name = tenant
- options_name = 'tenant'
- attribute_mapping = {'name': 'ou',
- 'description': 'description',
- 'tenantId': 'cn',
- 'enabled': 'enabled',
- 'domain_id': 'domain_id'}
- model = models.Project
-
- def __init__(self, conf):
- super(ProjectApi, self).__init__(conf)
- self.attribute_mapping['name'] = conf.ldap.tenant_name_attribute
- self.attribute_mapping['description'] = conf.ldap.tenant_desc_attribute
- self.attribute_mapping['enabled'] = conf.ldap.tenant_enabled_attribute
- self.attribute_mapping['domain_id'] = (
- conf.ldap.tenant_domain_id_attribute)
- self.member_attribute = (getattr(conf.ldap, 'tenant_member_attribute')
- or self.DEFAULT_MEMBER_ATTRIBUTE)
- self.attribute_ignore = (getattr(conf.ldap, 'tenant_attribute_ignore')
- or self.DEFAULT_ATTRIBUTE_IGNORE)
-
- def create(self, values):
- self.affirm_unique(values)
- data = values.copy()
- if data.get('id') is None:
- data['id'] = uuid.uuid4().hex
- return super(ProjectApi, self).create(data)
-
- def get_user_projects(self, user_dn, associations):
- """Returns list of tenants a user has access to
- """
-
- project_ids = set()
- for assoc in associations:
- project_ids.add(self._dn_to_id(assoc.project_dn))
- projects = []
- for project_id in project_ids:
- #slower to get them one at a time, but a huge list could blow out
- #the connection. This is the safer way
- projects.append(self.get(project_id))
- return projects
-
- def add_user(self, tenant_id, user_dn):
- conn = self.get_connection()
- try:
- conn.modify_s(
- self._id_to_dn(tenant_id),
- [(ldap.MOD_ADD,
- self.member_attribute,
- user_dn)])
- except ldap.TYPE_OR_VALUE_EXISTS:
- # As adding a user to a tenant is done implicitly in several
- # places, and is not part of the exposed API, it's easier for us to
- # just ignore this instead of raising exception.Conflict.
- pass
-
- def remove_user(self, tenant_id, user_dn, user_id):
- conn = self.get_connection()
- try:
- conn.modify_s(self._id_to_dn(tenant_id),
- [(ldap.MOD_DELETE,
- self.member_attribute,
- user_dn)])
- except ldap.NO_SUCH_ATTRIBUTE:
- raise exception.NotFound(user_id)
-
- def get_user_dns(self, tenant_id, rolegrants, role_dn=None):
- tenant = self._ldap_get(tenant_id)
- res = set()
- if not role_dn:
- # Get users who have default tenant mapping
- for user_dn in tenant[1].get(self.member_attribute, []):
- if self.use_dumb_member and user_dn == self.dumb_member:
- continue
- res.add(user_dn)
-
- # Get users who are explicitly mapped via a tenant
- for rolegrant in rolegrants:
- if role_dn is None or rolegrant.role_dn == role_dn:
- res.add(rolegrant.user_dn)
- return list(res)
-
- def update(self, id, values):
- old_obj = self.get(id)
- if old_obj['name'] != values['name']:
- msg = 'Changing Name not supported by LDAP'
- raise exception.NotImplemented(message=msg)
- return super(ProjectApi, self).update(id, values, old_obj)
-
-
-class UserRoleAssociation(object):
- """Role Grant model."""
-
- def __init__(self, user_dn=None, role_dn=None, tenant_dn=None,
- *args, **kw):
- self.user_dn = user_dn
- self.role_dn = role_dn
- self.project_dn = tenant_dn
-
-
-class GroupRoleAssociation(object):
- """Role Grant model."""
-
- def __init__(self, group_dn=None, role_dn=None, tenant_dn=None,
- *args, **kw):
- self.group_dn = group_dn
- self.role_dn = role_dn
- self.project_dn = tenant_dn
-
-
-# TODO(termie): turn this into a data object and move logic to driver
-class RoleApi(common_ldap.BaseLdap):
- DEFAULT_OU = 'ou=Roles'
- DEFAULT_STRUCTURAL_CLASSES = []
- DEFAULT_OBJECTCLASS = 'organizationalRole'
- DEFAULT_MEMBER_ATTRIBUTE = 'roleOccupant'
- DEFAULT_ATTRIBUTE_IGNORE = []
- NotFound = exception.RoleNotFound
- options_name = 'role'
- attribute_mapping = {'name': 'ou',
- #'serviceId': 'service_id',
- }
- model = models.Role
-
- def __init__(self, conf):
- super(RoleApi, self).__init__(conf)
- self.attribute_mapping['name'] = conf.ldap.role_name_attribute
- self.member_attribute = (getattr(conf.ldap, 'role_member_attribute')
- or self.DEFAULT_MEMBER_ATTRIBUTE)
- self.attribute_ignore = (getattr(conf.ldap, 'role_attribute_ignore')
- or self.DEFAULT_ATTRIBUTE_IGNORE)
-
- def get(self, id, filter=None):
- model = super(RoleApi, self).get(id, filter)
- return model
-
- def create(self, values):
- return super(RoleApi, self).create(values)
-
- def add_user(self, role_id, role_dn, user_dn, user_id, tenant_id=None):
- conn = self.get_connection()
- try:
- conn.modify_s(role_dn, [(ldap.MOD_ADD,
- self.member_attribute, user_dn)])
- except ldap.TYPE_OR_VALUE_EXISTS:
- msg = ('User %s already has role %s in tenant %s'
- % (user_id, role_id, tenant_id))
- raise exception.Conflict(type='role grant', details=msg)
- except ldap.NO_SUCH_OBJECT:
- if tenant_id is None or self.get(role_id) is None:
- raise Exception(_("Role %s not found") % (role_id,))
-
- attrs = [('objectClass', [self.object_class]),
- (self.member_attribute, [user_dn])]
-
- if self.use_dumb_member:
- attrs[1][1].append(self.dumb_member)
- try:
- conn.add_s(role_dn, attrs)
- except Exception as inst:
- raise inst
-
- def delete_user(self, role_dn, user_dn, tenant_dn,
- user_id, role_id):
- conn = self.get_connection()
- try:
- conn.modify_s(role_dn, [(ldap.MOD_DELETE,
- self.member_attribute, user_dn)])
- except ldap.NO_SUCH_OBJECT:
- if tenant_dn is None:
- raise exception.RoleNotFound(role_id=role_id)
- attrs = [('objectClass', [self.object_class]),
- (self.member_attribute, [user_dn])]
-
- if self.use_dumb_member:
- attrs[1][1].append(self.dumb_member)
- try:
- conn.add_s(role_dn, attrs)
- except Exception as inst:
- raise inst
- except ldap.NO_SUCH_ATTRIBUTE:
- raise exception.UserNotFound(user_id=user_id)
-
- def get_role_assignments(self, tenant_dn):
- conn = self.get_connection()
- query = '(objectClass=%s)' % self.object_class
-
- try:
- roles = conn.search_s(tenant_dn, ldap.SCOPE_ONELEVEL, query)
- except ldap.NO_SUCH_OBJECT:
- return []
-
- res = []
- for role_dn, attrs in roles:
- try:
- user_dns = attrs[self.member_attribute]
- except KeyError:
- continue
- for user_dn in user_dns:
- if self.use_dumb_member and user_dn == self.dumb_member:
- continue
- res.append(UserRoleAssociation(
- user_dn=user_dn,
- role_dn=role_dn,
- tenant_dn=tenant_dn))
-
- return res
-
- def list_global_roles_for_user(self, user_dn):
- roles = self.get_all('(%s=%s)' % (self.member_attribute, user_dn))
- return [UserRoleAssociation(
- role_dn=role.dn,
- user_dn=user_dn) for role in roles]
-
- def list_project_roles_for_user(self, user_dn, project_subtree):
- conn = self.get_connection()
- query = '(&(objectClass=%s)(%s=%s))' % (self.object_class,
- self.member_attribute,
- user_dn)
- try:
- roles = conn.search_s(project_subtree,
- ldap.SCOPE_SUBTREE,
- query)
- except ldap.NO_SUCH_OBJECT:
- return []
-
- res = []
- for role_dn, _ in roles:
- #ldap.dn.dn2str returns an array, where the first
- #element is the first segment.
- #For a role assignment, this contains the role ID,
- #The remainder is the DN of the tenant.
- tenant = ldap.dn.str2dn(role_dn)
- tenant.pop(0)
- tenant_dn = ldap.dn.dn2str(tenant)
- res.append(UserRoleAssociation(
- user_dn=user_dn,
- role_dn=role_dn,
- tenant_dn=tenant_dn))
- return res
-
- def roles_delete_subtree_by_project(self, tenant_dn):
- conn = self.get_connection()
- query = '(objectClass=%s)' % self.object_class
- try:
- roles = conn.search_s(tenant_dn, ldap.SCOPE_ONELEVEL, query)
- for role_dn, _ in roles:
- try:
- conn.delete_s(role_dn)
- except Exception as inst:
- raise inst
- except ldap.NO_SUCH_OBJECT:
- pass
-
- def update(self, role_id, role):
- if role['id'] != role_id:
- raise exception.ValidationError('Cannot change role ID')
- try:
- old_name = self.get_by_name(role['name'])
- raise exception.Conflict('Cannot duplicate name %s' % old_name)
- except exception.NotFound:
- pass
- return super(RoleApi, self).update(role_id, role)
-
- def delete(self, id, tenant_dn):
- conn = self.get_connection()
- query = '(&(objectClass=%s)(%s=%s))' % (self.object_class,
- self.id_attr, id)
- try:
- for role_dn, _ in conn.search_s(tenant_dn,
- ldap.SCOPE_SUBTREE,
- query):
- conn.delete_s(role_dn)
- except ldap.NO_SUCH_OBJECT:
- pass
- super(RoleApi, self).delete(id)
-
-
class GroupApi(common_ldap.BaseLdap):
DEFAULT_OU = 'ou=UserGroups'
DEFAULT_STRUCTURAL_CLASSES = []
diff --git a/keystone/identity/backends/pam.py b/keystone/identity/backends/pam.py
index 5cfa5b16..2a6ee621 100644
--- a/keystone/identity/backends/pam.py
+++ b/keystone/identity/backends/pam.py
@@ -58,7 +58,7 @@ class PamIdentity(identity.Driver):
Tenant is always the same as User, root user has admin role.
"""
- def authenticate(self, user_id=None, password=None):
+ def authenticate(self, user_id, password):
auth = pam.authenticate if pam else PAM_authenticate
if not auth(user_id, password):
raise AssertionError('Invalid user / password')
diff --git a/keystone/identity/backends/sql.py b/keystone/identity/backends/sql.py
index 2c00088e..ba97758c 100644
--- a/keystone/identity/backends/sql.py
+++ b/keystone/identity/backends/sql.py
@@ -84,7 +84,7 @@ class Identity(sql.Base, identity.Driver):
return utils.check_password(password, user_ref.password)
# Identity interface
- def authenticate(self, user_id=None, password=None):
+ def authenticate(self, user_id, password):
session = self.get_session()
user_ref = None
try:
diff --git a/keystone/identity/core.py b/keystone/identity/core.py
index b3efc0a7..3d9bcf62 100644
--- a/keystone/identity/core.py
+++ b/keystone/identity/core.py
@@ -216,7 +216,7 @@ class Manager(manager.Manager):
class Driver(object):
"""Interface description for an Identity driver."""
- def authenticate_user(self, user_id, password):
+ def authenticate(self, user_id, password):
"""Authenticate a given user and password.
:returns: user_ref
:raises: AssertionError
diff --git a/keystone/test.py b/keystone/test.py
index 0c51d76d..2c2be577 100644
--- a/keystone/test.py
+++ b/keystone/test.py
@@ -44,6 +44,7 @@ from keystone.common import sql
from keystone.common import utils
from keystone.common import wsgi
from keystone import config
+from keystone.contrib import ec2
from keystone import credential
from keystone import exception
from keystone import identity
@@ -252,7 +253,7 @@ class TestCase(NoModule, unittest.TestCase):
def load_backends(self):
"""Initializes each manager and assigns them to an attribute."""
- for manager in [assignment, catalog, credential, identity, policy,
+ for manager in [assignment, catalog, credential, ec2, identity, policy,
token, trust]:
manager_name = '%s_api' % manager.__name__.split('.')[-1]
setattr(self, manager_name, manager.Manager())
diff --git a/keystone/token/provider.py b/keystone/token/provider.py
index 2459f843..2864be6f 100644
--- a/keystone/token/provider.py
+++ b/keystone/token/provider.py
@@ -77,6 +77,10 @@ class Manager(manager.Manager):
'conflicts with keystone.conf [token] provider'))
return CONF.token.provider
else:
+ if not CONF.signing.token_format:
+ # No token provider and no format, so use default (PKI)
+ return PKI_PROVIDER
+
msg = _('keystone.conf [signing] token_format is deprecated in '
'favor of keystone.conf [token] provider')
if CONF.signing.token_format == 'PKI':
diff --git a/tests/_ldap_livetest.py b/tests/_ldap_livetest.py
index 0bd707a4..ead54ea7 100644
--- a/tests/_ldap_livetest.py
+++ b/tests/_ldap_livetest.py
@@ -16,7 +16,6 @@
import ldap
import ldap.modlist
-import nose.exc
import subprocess
from keystone.common import ldap as ldap_common
@@ -89,7 +88,7 @@ class LiveLDAPIdentity(test_backend_ldap.LDAPIdentity):
test.TestCase.tearDown(self)
def test_user_enable_attribute_mask(self):
- raise nose.exc.SkipTest('Test is for Active Directory Only')
+ self.skipTest('Test is for Active Directory Only')
def test_ldap_dereferencing(self):
alt_users_ldif = {'objectclass': ['top', 'organizationalUnit'],
diff --git a/tests/test_backend_kvs.py b/tests/test_backend_kvs.py
index 0c6c2abe..d92a7510 100644
--- a/tests/test_backend_kvs.py
+++ b/tests/test_backend_kvs.py
@@ -15,8 +15,6 @@
# under the License.
import uuid
-import nose.exc
-
from keystone import test
from keystone import exception
@@ -36,34 +34,34 @@ class KvsIdentity(test.TestCase, test_backend.IdentityTests):
def test_list_user_projects(self):
# NOTE(chungg): not implemented
- raise nose.exc.SkipTest('Blocked by bug 1119770')
+ self.skipTest('Blocked by bug 1119770')
def test_create_duplicate_group_name_in_different_domains(self):
- raise nose.exc.SkipTest('Blocked by bug 1119770')
+ self.skipTest('Blocked by bug 1119770')
def test_create_duplicate_user_name_in_different_domains(self):
- raise nose.exc.SkipTest('Blocked by bug 1119770')
+ self.skipTest('Blocked by bug 1119770')
def test_create_duplicate_project_name_in_different_domains(self):
- raise nose.exc.SkipTest('Blocked by bug 1119770')
+ self.skipTest('Blocked by bug 1119770')
def test_move_user_between_domains(self):
- raise nose.exc.SkipTest('Blocked by bug 1119770')
+ self.skipTest('Blocked by bug 1119770')
def test_move_user_between_domains_with_clashing_names_fails(self):
- raise nose.exc.SkipTest('Blocked by bug 1119770')
+ self.skipTest('Blocked by bug 1119770')
def test_move_group_between_domains(self):
- raise nose.exc.SkipTest('Blocked by bug 1119770')
+ self.skipTest('Blocked by bug 1119770')
def test_move_group_between_domains_with_clashing_names_fails(self):
- raise nose.exc.SkipTest('Blocked by bug 1119770')
+ self.skipTest('Blocked by bug 1119770')
def test_move_project_between_domains(self):
- raise nose.exc.SkipTest('Blocked by bug 1119770')
+ self.skipTest('Blocked by bug 1119770')
def test_move_project_between_domains_with_clashing_names_fails(self):
- raise nose.exc.SkipTest('Blocked by bug 1119770')
+ self.skipTest('Blocked by bug 1119770')
class KvsToken(test.TestCase, test_backend.TokenTests):
diff --git a/tests/test_backend_ldap.py b/tests/test_backend_ldap.py
index ce4a297c..ec2b2737 100644
--- a/tests/test_backend_ldap.py
+++ b/tests/test_backend_ldap.py
@@ -17,8 +17,6 @@
import uuid
-import nose.exc
-
from keystone import assignment
from keystone.common.ldap import fakeldap
from keystone.common import sql
@@ -109,93 +107,93 @@ class BaseLDAPIdentity(test_backend.IdentityTests):
self.user_foo['id'])
def test_get_role_grant_by_user_and_project(self):
- raise nose.exc.SkipTest('Blocked by bug 1101287')
+ self.skipTest('Blocked by bug 1101287')
def test_get_role_grants_for_user_and_project_404(self):
- raise nose.exc.SkipTest('Blocked by bug 1101287')
+ self.skipTest('Blocked by bug 1101287')
def test_add_role_grant_to_user_and_project_404(self):
- raise nose.exc.SkipTest('Blocked by bug 1101287')
+ self.skipTest('Blocked by bug 1101287')
def test_remove_role_grant_from_user_and_project(self):
- raise nose.exc.SkipTest('Blocked by bug 1101287')
+ self.skipTest('Blocked by bug 1101287')
def test_get_and_remove_role_grant_by_group_and_project(self):
- raise nose.exc.SkipTest('Blocked by bug 1101287')
+ self.skipTest('Blocked by bug 1101287')
def test_get_and_remove_role_grant_by_group_and_domain(self):
- raise nose.exc.SkipTest('N/A: LDAP does not support multiple domains')
+ self.skipTest('N/A: LDAP does not support multiple domains')
def test_get_and_remove_role_grant_by_user_and_domain(self):
- raise nose.exc.SkipTest('N/A: LDAP does not support multiple domains')
+ self.skipTest('N/A: LDAP does not support multiple domains')
def test_get_and_remove_correct_role_grant_from_a_mix(self):
- raise nose.exc.SkipTest('Blocked by bug 1101287')
+ self.skipTest('Blocked by bug 1101287')
def test_get_and_remove_role_grant_by_group_and_cross_domain(self):
- raise nose.exc.SkipTest('N/A: LDAP does not support multiple domains')
+ self.skipTest('N/A: LDAP does not support multiple domains')
def test_get_and_remove_role_grant_by_user_and_cross_domain(self):
- raise nose.exc.SkipTest('N/A: LDAP does not support multiple domains')
+ self.skipTest('N/A: LDAP does not support multiple domains')
def test_role_grant_by_group_and_cross_domain_project(self):
- raise nose.exc.SkipTest('N/A: LDAP does not support multiple domains')
+ self.skipTest('N/A: LDAP does not support multiple domains')
def test_role_grant_by_user_and_cross_domain_project(self):
- raise nose.exc.SkipTest('N/A: LDAP does not support multiple domains')
+ self.skipTest('N/A: LDAP does not support multiple domains')
def test_multi_role_grant_by_user_group_on_project_domain(self):
- raise nose.exc.SkipTest('N/A: LDAP does not support multiple domains')
+ self.skipTest('N/A: LDAP does not support multiple domains')
def test_delete_role_with_user_and_group_grants(self):
- raise nose.exc.SkipTest('Blocked by bug 1101287')
+ self.skipTest('Blocked by bug 1101287')
def test_delete_user_with_group_project_domain_links(self):
- raise nose.exc.SkipTest('N/A: LDAP does not support multiple domains')
+ self.skipTest('N/A: LDAP does not support multiple domains')
def test_delete_group_with_user_project_domain_links(self):
- raise nose.exc.SkipTest('N/A: LDAP does not support multiple domains')
+ self.skipTest('N/A: LDAP does not support multiple domains')
def test_list_user_projects(self):
- raise nose.exc.SkipTest('Blocked by bug 1101287')
+ self.skipTest('Blocked by bug 1101287')
def test_create_duplicate_user_name_in_different_domains(self):
- raise nose.exc.SkipTest('Blocked by bug 1101276')
+ self.skipTest('Blocked by bug 1101276')
def test_create_duplicate_project_name_in_different_domains(self):
- raise nose.exc.SkipTest('Blocked by bug 1101276')
+ self.skipTest('Blocked by bug 1101276')
def test_create_duplicate_group_name_in_different_domains(self):
- raise nose.exc.SkipTest(
+ self.skipTest(
'N/A: LDAP does not support multiple domains')
def test_move_user_between_domains(self):
- raise nose.exc.SkipTest('Blocked by bug 1101276')
+ self.skipTest('Blocked by bug 1101276')
def test_move_user_between_domains_with_clashing_names_fails(self):
- raise nose.exc.SkipTest('Blocked by bug 1101276')
+ self.skipTest('Blocked by bug 1101276')
def test_move_group_between_domains(self):
- raise nose.exc.SkipTest(
+ self.skipTest(
'N/A: LDAP does not support multiple domains')
def test_move_group_between_domains_with_clashing_names_fails(self):
- raise nose.exc.SkipTest('Blocked by bug 1101276')
+ self.skipTest('Blocked by bug 1101276')
def test_move_project_between_domains(self):
- raise nose.exc.SkipTest('Blocked by bug 1101276')
+ self.skipTest('Blocked by bug 1101276')
def test_move_project_between_domains_with_clashing_names_fails(self):
- raise nose.exc.SkipTest('Blocked by bug 1101276')
+ self.skipTest('Blocked by bug 1101276')
def test_get_roles_for_user_and_domain(self):
- raise nose.exc.SkipTest('N/A: LDAP does not support multiple domains')
+ self.skipTest('N/A: LDAP does not support multiple domains')
def test_list_role_assignments_unfiltered(self):
- raise nose.exc.SkipTest('Blocked by bug 1195019')
+ self.skipTest('Blocked by bug 1195019')
def test_multi_group_grants_on_project_domain(self):
- raise nose.exc.SkipTest('Blocked by bug 1101287')
+ self.skipTest('Blocked by bug 1101287')
def test_list_group_members_missing_entry(self):
"""List group members with deleted user.
@@ -562,12 +560,12 @@ class LDAPIdentity(test.TestCase, BaseLDAPIdentity):
'domain_id': CONF.identity.default_domain_id,
'description': uuid.uuid4().hex
}
- self.identity_api.driver.create_project(project['id'], project)
- project_ref = self.identity_api.driver.get_project(project['id'])
+ self.assignment_api.create_project(project['id'], project)
+ project_ref = self.assignment_api.get_project(project['id'])
# NOTE(crazed): If running live test with emulation, there will be
# an enabled key in the project_ref.
- if self.identity_api.driver.project.enabled_emulation:
+ if self.assignment_api.driver.project.enabled_emulation:
project['enabled'] = True
self.assertDictEqual(project_ref, project)
@@ -631,7 +629,7 @@ class LDAPIdentity(test.TestCase, BaseLDAPIdentity):
self.assertEquals(len(combined_role_list), 0)
def test_list_projects_for_alternate_domain(self):
- raise nose.exc.SkipTest(
+ self.skipTest(
'N/A: LDAP does not support multiple domains')
@@ -705,7 +703,7 @@ class LDAPIdentityEnabledEmulation(LDAPIdentity):
user['id'])
def test_user_enable_attribute_mask(self):
- raise nose.exc.SkipTest(
+ self.skipTest(
"Enabled emulation conflicts with enabled mask")
@@ -739,9 +737,9 @@ class LdapIdentitySqlAssignment(sql.Base, test.TestCase, BaseLDAPIdentity):
self.assertEquals(domains, [assignment.DEFAULT_DOMAIN])
def test_project_filter(self):
- raise nose.exc.SkipTest(
+ self.skipTest(
'N/A: Not part of SQL backend')
def test_role_filter(self):
- raise nose.exc.SkipTest(
+ self.skipTest(
'N/A: Not part of SQL backend')
diff --git a/tests/test_content_types.py b/tests/test_content_types.py
index 3213656c..ebb5dcef 100644
--- a/tests/test_content_types.py
+++ b/tests/test_content_types.py
@@ -18,7 +18,6 @@ import io
import uuid
from lxml import etree
-import nose.exc
import webtest
from keystone import test
@@ -471,7 +470,7 @@ class CoreApiTests(object):
self.assertValidTenantResponse(r)
def test_get_user_roles(self):
- raise nose.exc.SkipTest('Blocked by bug 933565')
+ self.skipTest('Blocked by bug 933565')
token = self.get_scoped_token()
r = self.admin_request(
diff --git a/tests/test_exception.py b/tests/test_exception.py
index 33250835..d442d572 100644
--- a/tests/test_exception.py
+++ b/tests/test_exception.py
@@ -67,14 +67,14 @@ class ExceptionTestCase(test.TestCase):
attribute = uuid.uuid4().hex
e = exception.ValidationError(target=target, attribute=attribute)
self.assertValidJsonRendering(e)
- self.assertIn(target, str(e))
- self.assertIn(attribute, str(e))
+ self.assertIn(target, unicode(e))
+ self.assertIn(attribute, unicode(e))
def test_not_found(self):
target = uuid.uuid4().hex
e = exception.NotFound(target=target)
self.assertValidJsonRendering(e)
- self.assertIn(target, str(e))
+ self.assertIn(target, unicode(e))
def test_403_title(self):
e = exception.Forbidden()
@@ -101,7 +101,7 @@ class SecurityErrorTestCase(ExceptionTestCase):
risky_info = uuid.uuid4().hex
e = exception.Unauthorized(message=risky_info)
self.assertValidJsonRendering(e)
- self.assertNotIn(risky_info, str(e))
+ self.assertNotIn(risky_info, unicode(e))
def test_unauthorized_exposure_in_debug(self):
self.opt(debug=True)
@@ -109,7 +109,7 @@ class SecurityErrorTestCase(ExceptionTestCase):
risky_info = uuid.uuid4().hex
e = exception.Unauthorized(message=risky_info)
self.assertValidJsonRendering(e)
- self.assertIn(risky_info, str(e))
+ self.assertIn(risky_info, unicode(e))
def test_forbidden_exposure(self):
self.opt(debug=False)
@@ -117,7 +117,7 @@ class SecurityErrorTestCase(ExceptionTestCase):
risky_info = uuid.uuid4().hex
e = exception.Forbidden(message=risky_info)
self.assertValidJsonRendering(e)
- self.assertNotIn(risky_info, str(e))
+ self.assertNotIn(risky_info, unicode(e))
def test_forbidden_exposure_in_debug(self):
self.opt(debug=True)
@@ -125,7 +125,7 @@ class SecurityErrorTestCase(ExceptionTestCase):
risky_info = uuid.uuid4().hex
e = exception.Forbidden(message=risky_info)
self.assertValidJsonRendering(e)
- self.assertIn(risky_info, str(e))
+ self.assertIn(risky_info, unicode(e))
def test_forbidden_action_exposure(self):
self.opt(debug=False)
@@ -134,12 +134,12 @@ class SecurityErrorTestCase(ExceptionTestCase):
action = uuid.uuid4().hex
e = exception.ForbiddenAction(message=risky_info, action=action)
self.assertValidJsonRendering(e)
- self.assertNotIn(risky_info, str(e))
- self.assertIn(action, str(e))
+ self.assertNotIn(risky_info, unicode(e))
+ self.assertIn(action, unicode(e))
e = exception.ForbiddenAction(action=risky_info)
self.assertValidJsonRendering(e)
- self.assertIn(risky_info, str(e))
+ self.assertIn(risky_info, unicode(e))
def test_forbidden_action_exposure_in_debug(self):
self.opt(debug=True)
@@ -148,8 +148,16 @@ class SecurityErrorTestCase(ExceptionTestCase):
e = exception.ForbiddenAction(message=risky_info)
self.assertValidJsonRendering(e)
- self.assertIn(risky_info, str(e))
+ self.assertIn(risky_info, unicode(e))
e = exception.ForbiddenAction(action=risky_info)
self.assertValidJsonRendering(e)
- self.assertIn(risky_info, str(e))
+ self.assertIn(risky_info, unicode(e))
+
+ def test_unicode_argument_message(self):
+ self.opt(debug=False)
+
+ risky_info = u'\u7ee7\u7eed\u884c\u7f29\u8fdb\u6216'
+ e = exception.Forbidden(message=risky_info)
+ self.assertValidJsonRendering(e)
+ self.assertNotIn(risky_info, unicode(e))
diff --git a/tests/test_keystoneclient.py b/tests/test_keystoneclient.py
index dc494b3f..a26d6595 100644
--- a/tests/test_keystoneclient.py
+++ b/tests/test_keystoneclient.py
@@ -17,8 +17,6 @@
import uuid
import webob
-import nose.exc
-
from keystone import test
from keystone import token
@@ -541,7 +539,7 @@ class KeystoneClientTests(object):
user=uuid.uuid4().hex)
def test_user_update_tenant_404(self):
- raise nose.exc.SkipTest('N/A')
+ self.skipTest('N/A')
from keystoneclient import exceptions as client_exceptions
client = self.get_client(admin=True)
self.assertRaises(client_exceptions.NotFound,
@@ -1112,10 +1110,10 @@ class KcEssex3TestCase(CompatTestCase, KeystoneClientTests):
self.assertTrue(len(roles) > 0)
def test_role_list_404(self):
- raise nose.exc.SkipTest('N/A')
+ self.skipTest('N/A')
def test_authenticate_and_delete_token(self):
- raise nose.exc.SkipTest('N/A')
+ self.skipTest('N/A')
def test_user_create_update_delete(self):
from keystoneclient import exceptions as client_exceptions
@@ -1159,16 +1157,16 @@ class KcEssex3TestCase(CompatTestCase, KeystoneClientTests):
user.id)
def test_user_update_404(self):
- raise nose.exc.SkipTest('N/A')
+ self.skipTest('N/A')
def test_endpoint_create_404(self):
- raise nose.exc.SkipTest('N/A')
+ self.skipTest('N/A')
def test_endpoint_delete_404(self):
- raise nose.exc.SkipTest('N/A')
+ self.skipTest('N/A')
def test_policy_crud(self):
- raise nose.exc.SkipTest('N/A due to lack of endpoint CRUD')
+ self.skipTest('N/A due to lack of endpoint CRUD')
class Kc11TestCase(CompatTestCase, KeystoneClientTests):
@@ -1176,4 +1174,4 @@ class Kc11TestCase(CompatTestCase, KeystoneClientTests):
return KEYSTONECLIENT_REPO, '0.1.1'
def test_policy_crud(self):
- raise nose.exc.SkipTest('N/A')
+ self.skipTest('N/A')
diff --git a/tests/test_keystoneclient_sql.py b/tests/test_keystoneclient_sql.py
index 5706bef5..166d808c 100644
--- a/tests/test_keystoneclient_sql.py
+++ b/tests/test_keystoneclient_sql.py
@@ -16,8 +16,6 @@
import uuid
-import nose.exc
-
from keystone import test
from keystone.common import sql
@@ -109,7 +107,7 @@ class KcMasterSqlTestCase(test_keystoneclient.KcMasterTestCase, sql.Base):
# the client and essentially refers to a non-existent
# policy manager in the v2 client. this test needs to be
# moved to a test suite running against the v3 api
- raise nose.exc.SkipTest('Written prior to v3 client; needs refactor')
+ self.skipTest('Written prior to v3 client; needs refactor')
from keystoneclient import exceptions as client_exceptions
client = self.get_client(admin=True)
diff --git a/tests/test_pki_token_provider.conf b/tests/test_pki_token_provider.conf
index ec8df231..255972c3 100644
--- a/tests/test_pki_token_provider.conf
+++ b/tests/test_pki_token_provider.conf
@@ -1,5 +1,2 @@
-[signing]
-token_format = PKI
-
[token]
provider = keystone.token.providers.pki.Provider
diff --git a/tests/test_sql_core.py b/tests/test_sql_core.py
index bb413485..e60005f5 100644
--- a/tests/test_sql_core.py
+++ b/tests/test_sql_core.py
@@ -172,3 +172,11 @@ class TestBase(test.TestCase):
self.assertFalse(session.autocommit)
self.assertTrue(session.expire_on_commit)
+
+ def test_get_session_invalidated(self):
+ # If clear the global engine, a new engine is used for get_session().
+ base = sql.Base()
+ session1 = base.get_session()
+ sql.set_global_engine(None)
+ session2 = base.get_session()
+ self.assertIsNot(session1.bind, session2.bind)
diff --git a/tests/test_token_provider.py b/tests/test_token_provider.py
index 1bcf1a21..ac0b0d6b 100644
--- a/tests/test_token_provider.py
+++ b/tests/test_token_provider.py
@@ -410,11 +410,16 @@ class TestTokenProvider(test.TestCase):
self.assertRaises(exception.UnexpectedError,
token.provider.Manager.get_token_provider)
+ def test_uuid_provider(self):
+ self.opt_in_group('token', provider=token.provider.UUID_PROVIDER)
+ self.assertEqual(token.provider.Manager.get_token_provider(),
+ token.provider.UUID_PROVIDER)
+
def test_provider_override_token_format(self):
self.opt_in_group('token',
provider='keystone.token.providers.pki.Test')
- self.assertRaises(exception.UnexpectedError,
- token.provider.Manager.get_token_provider)
+ self.assertEqual(token.provider.Manager.get_token_provider(),
+ 'keystone.token.providers.pki.Test')
self.opt_in_group('signing', token_format='UUID')
self.opt_in_group('token',
diff --git a/tests/test_uuid_token_provider.conf b/tests/test_uuid_token_provider.conf
index d1ac5fdf..d127ea3b 100644
--- a/tests/test_uuid_token_provider.conf
+++ b/tests/test_uuid_token_provider.conf
@@ -1,5 +1,2 @@
-[signing]
-token_format = UUID
-
[token]
provider = keystone.token.providers.uuid.Provider
diff --git a/tests/test_v3_auth.py b/tests/test_v3_auth.py
index 2e354f71..11d66700 100644
--- a/tests/test_v3_auth.py
+++ b/tests/test_v3_auth.py
@@ -15,8 +15,6 @@
import json
import uuid
-import nose.exc
-
from keystone import auth
from keystone.common import cms
from keystone import config
@@ -1438,7 +1436,7 @@ class TestTrustAuth(TestAuthInfo):
self.identity_api.create_user(self.trustee_user_id, self.trustee_user)
def test_create_trust_400(self):
- raise nose.exc.SkipTest('Blocked by bug 1133435')
+ self.skipTest('Blocked by bug 1133435')
self.post('/OS-TRUST/trusts', body={'trust': {}}, expected_status=400)
def test_create_unscoped_trust(self):
diff --git a/tests/test_wsgi.py b/tests/test_wsgi.py
index 8ac594a8..369dd952 100644
--- a/tests/test_wsgi.py
+++ b/tests/test_wsgi.py
@@ -134,6 +134,11 @@ class ApplicationTest(BaseWSGITest):
self.assertIn("testkey", app.kwargs)
self.assertEquals("test", app.kwargs["testkey"])
+ def test_render_exception(self):
+ e = exception.Unauthorized(message=u'\u7f51\u7edc')
+ resp = wsgi.render_exception(e)
+ self.assertEqual(resp.status_int, 401)
+
class ExtensionRouterTest(BaseWSGITest):
def test_extensionrouter_local_config(self):