From 29951be74806020b579690faa084de0728fc0201 Mon Sep 17 00:00:00 2001 From: Morgan Fainberg Date: Sun, 29 Jan 2017 14:08:21 -0800 Subject: [PATCH] Cleanup TODO, AuthContext and AuthInfo to auth.core Moved AuthContext and AuthInfo to keystone.auth.core as they are shared code bits and not exclusively controller specific. Change-Id: I649690d9e39057249e674500d85a053e0c28b30e --- keystone/auth/controllers.py | 292 +----------------- keystone/auth/core.py | 276 +++++++++++++++++ keystone/common/tokenless_auth.py | 4 +- keystone/tests/unit/test_auth_plugin.py | 22 +- keystone/tests/unit/test_v3.py | 4 +- keystone/tests/unit/test_v3_auth.py | 22 +- .../tests/unit/token/test_fernet_provider.py | 2 +- 7 files changed, 309 insertions(+), 313 deletions(-) diff --git a/keystone/auth/controllers.py b/keystone/auth/controllers.py index 9451bf4a0c..bdc7ba569c 100644 --- a/keystone/auth/controllers.py +++ b/keystone/auth/controllers.py @@ -12,8 +12,6 @@ # License for the specific language governing permissions and limitations # under the License. -import sys - from keystoneclient.common import cms from oslo_log import log from oslo_serialization import jsonutils @@ -29,7 +27,7 @@ from keystone.common import wsgi import keystone.conf from keystone import exception from keystone.federation import constants -from keystone.i18n import _, _LI, _LW, _LE +from keystone.i18n import _, _LW, _LE from keystone.resource import controllers as resource_controllers @@ -38,284 +36,6 @@ LOG = log.getLogger(__name__) CONF = keystone.conf.CONF -# TODO(notmorgan): Move Common Auth Code (AuthContext and AuthInfo) -# loading into keystone.auth.core (and update all references to the new -# locations) - - -class AuthContext(dict): - """Retrofitting auth_context to reconcile identity attributes. - - The identity attributes must not have conflicting values among the - auth plug-ins. The only exception is `expires_at`, which is set to its - earliest value. - - """ - - # identity attributes need to be reconciled among the auth plugins - IDENTITY_ATTRIBUTES = frozenset(['user_id', 'project_id', - 'access_token_id', 'domain_id', - 'expires_at']) - - def __setitem__(self, key, val): - """Override __setitem__ to prevent conflicting values.""" - if key in self.IDENTITY_ATTRIBUTES and key in self: - existing_val = self[key] - if key == 'expires_at': - # special treatment for 'expires_at', we are going to take - # the earliest expiration instead. - if existing_val != val: - LOG.info(_LI('"expires_at" has conflicting values ' - '%(existing)s and %(new)s. Will use the ' - 'earliest value.'), - {'existing': existing_val, 'new': val}) - if existing_val is None or val is None: - val = existing_val or val - else: - val = min(existing_val, val) - elif existing_val != val: - msg = _('Unable to reconcile identity attribute %(attribute)s ' - 'as it has conflicting values %(new)s and %(old)s') % ( - {'attribute': key, - 'new': val, - 'old': existing_val}) - raise exception.Unauthorized(msg) - return super(AuthContext, self).__setitem__(key, val) - - def update(self, E=None, **F): - """Override update to prevent conflicting values.""" - # NOTE(notmorgan): This will not be nearly as performant as the - # use of the built-in "update" method on the dict, however, the - # volume of data being changed here is very minimal in most cases - # and should not see a significant impact by iterating instead of - # explicit setting of values. - update_dicts = (E or {}, F or {}) - for d in update_dicts: - for key, val in d.items(): - self[key] = val - - -@dependency.requires('resource_api', 'trust_api') -class AuthInfo(object): - """Encapsulation of "auth" request.""" - - @staticmethod - def create(auth=None, scope_only=False): - auth_info = AuthInfo(auth=auth) - auth_info._validate_and_normalize_auth_data(scope_only) - return auth_info - - def __init__(self, auth=None): - self.auth = auth - self._scope_data = (None, None, None, None) - # self._scope_data is (domain_id, project_id, trust_ref, unscoped) - # project scope: (None, project_id, None, None) - # domain scope: (domain_id, None, None, None) - # trust scope: (None, None, trust_ref, None) - # unscoped: (None, None, None, 'unscoped') - - def _assert_project_is_enabled(self, project_ref): - # ensure the project is enabled - try: - self.resource_api.assert_project_enabled( - project_id=project_ref['id'], - project=project_ref) - except AssertionError as e: - LOG.warning(six.text_type(e)) - six.reraise(exception.Unauthorized, exception.Unauthorized(e), - sys.exc_info()[2]) - - def _assert_domain_is_enabled(self, domain_ref): - try: - self.resource_api.assert_domain_enabled( - domain_id=domain_ref['id'], - domain=domain_ref) - except AssertionError as e: - LOG.warning(six.text_type(e)) - six.reraise(exception.Unauthorized, exception.Unauthorized(e), - sys.exc_info()[2]) - - def _lookup_domain(self, domain_info): - domain_id = domain_info.get('id') - domain_name = domain_info.get('name') - try: - if domain_name: - if (CONF.resource.domain_name_url_safe == 'strict' and - utils.is_not_url_safe(domain_name)): - msg = _('Domain name cannot contain reserved characters.') - LOG.warning(msg) - raise exception.Unauthorized(message=msg) - domain_ref = self.resource_api.get_domain_by_name( - domain_name) - else: - domain_ref = self.resource_api.get_domain(domain_id) - except exception.DomainNotFound as e: - LOG.warning(six.text_type(e)) - raise exception.Unauthorized(e) - self._assert_domain_is_enabled(domain_ref) - return domain_ref - - def _lookup_project(self, project_info): - project_id = project_info.get('id') - project_name = project_info.get('name') - try: - if project_name: - if (CONF.resource.project_name_url_safe == 'strict' and - utils.is_not_url_safe(project_name)): - msg = _('Project name cannot contain reserved characters.') - LOG.warning(msg) - raise exception.Unauthorized(message=msg) - if 'domain' not in project_info: - raise exception.ValidationError(attribute='domain', - target='project') - domain_ref = self._lookup_domain(project_info['domain']) - project_ref = self.resource_api.get_project_by_name( - project_name, domain_ref['id']) - else: - project_ref = self.resource_api.get_project(project_id) - # NOTE(morganfainberg): The _lookup_domain method will raise - # exception.Unauthorized if the domain isn't found or is - # disabled. - self._lookup_domain({'id': project_ref['domain_id']}) - except exception.ProjectNotFound as e: - LOG.warning(six.text_type(e)) - raise exception.Unauthorized(e) - self._assert_project_is_enabled(project_ref) - return project_ref - - def _lookup_trust(self, trust_info): - trust_id = trust_info.get('id') - if not trust_id: - raise exception.ValidationError(attribute='trust_id', - target='trust') - trust = self.trust_api.get_trust(trust_id) - return trust - - def _validate_and_normalize_scope_data(self): - """Validate and normalize scope data.""" - if 'scope' not in self.auth: - return - if sum(['project' in self.auth['scope'], - 'domain' in self.auth['scope'], - 'unscoped' in self.auth['scope'], - 'OS-TRUST:trust' in self.auth['scope']]) != 1: - raise exception.ValidationError( - attribute='project, domain, OS-TRUST:trust or unscoped', - target='scope') - if 'unscoped' in self.auth['scope']: - self._scope_data = (None, None, None, 'unscoped') - return - if 'project' in self.auth['scope']: - project_ref = self._lookup_project(self.auth['scope']['project']) - self._scope_data = (None, project_ref['id'], None, None) - elif 'domain' in self.auth['scope']: - domain_ref = self._lookup_domain(self.auth['scope']['domain']) - self._scope_data = (domain_ref['id'], None, None, None) - elif 'OS-TRUST:trust' in self.auth['scope']: - if not CONF.trust.enabled: - raise exception.Forbidden('Trusts are disabled.') - trust_ref = self._lookup_trust( - self.auth['scope']['OS-TRUST:trust']) - # TODO(ayoung): when trusts support domains, fill in domain data - if trust_ref.get('project_id') is not None: - project_ref = self._lookup_project( - {'id': trust_ref['project_id']}) - self._scope_data = (None, project_ref['id'], trust_ref, None) - else: - self._scope_data = (None, None, trust_ref, None) - - def _validate_auth_methods(self): - # make sure all the method data/payload are provided - for method_name in self.get_method_names(): - if method_name not in self.auth['identity']: - raise exception.ValidationError(attribute=method_name, - target='identity') - - # make sure auth method is supported - for method_name in self.get_method_names(): - if method_name not in core.AUTH_METHODS: - raise exception.AuthMethodNotSupported() - - def _validate_and_normalize_auth_data(self, scope_only=False): - """Make sure "auth" is valid. - - :param scope_only: If it is True, auth methods will not be - validated but only the scope data. - :type scope_only: boolean - """ - # make sure "auth" exist - if not self.auth: - raise exception.ValidationError(attribute='auth', - target='request body') - - # NOTE(chioleong): Tokenless auth does not provide auth methods, - # we only care about using this method to validate the scope - # information. Therefore, validating the auth methods here is - # insignificant and we can skip it when scope_only is set to - # true. - if scope_only is False: - self._validate_auth_methods() - self._validate_and_normalize_scope_data() - - def get_method_names(self): - """Return the identity method names. - - :returns: list of auth method names - - """ - # Sanitizes methods received in request's body - # Filters out duplicates, while keeping elements' order. - method_names = [] - for method in self.auth['identity']['methods']: - if method not in method_names: - method_names.append(method) - return method_names - - def get_method_data(self, method): - """Get the auth method payload. - - :returns: auth method payload - - """ - if method not in self.auth['identity']['methods']: - raise exception.ValidationError(attribute=method, - target='identity') - return self.auth['identity'][method] - - def get_scope(self): - """Get scope information. - - Verify and return the scoping information. - - :returns: (domain_id, project_id, trust_ref, unscoped). - If scope to a project, (None, project_id, None, None) - will be returned. - If scoped to a domain, (domain_id, None, None, None) - will be returned. - If scoped to a trust, (None, project_id, trust_ref, None), - Will be returned, where the project_id comes from the - trust definition. - If unscoped, (None, None, None, 'unscoped') will be - returned. - - """ - return self._scope_data - - def set_scope(self, domain_id=None, project_id=None, trust=None, - unscoped=None): - """Set scope information.""" - if domain_id and project_id: - msg = _('Scoping to both domain and project is not allowed') - raise ValueError(msg) - if domain_id and trust: - msg = _('Scoping to both domain and trust is not allowed') - raise ValueError(msg) - if project_id and trust: - msg = _('Scoping to both project and trust is not allowed') - raise ValueError(msg) - self._scope_data = (domain_id, project_id, trust, unscoped) - - def validate_issue_token_auth(auth=None): if auth is None: return @@ -390,10 +110,10 @@ class Auth(controller.V3Controller): validate_issue_token_auth(auth) try: - auth_info = AuthInfo.create(auth=auth) - auth_context = AuthContext(extras={}, - method_names=[], - bind={}) + auth_info = core.AuthInfo.create(auth=auth) + auth_context = core.AuthContext(extras={}, + method_names=[], + bind={}) self.authenticate(request, auth_info, auth_context) if auth_context.get('access_token_id'): auth_info.set_scope(None, auth_context['project_id'], None) @@ -505,7 +225,7 @@ class Auth(controller.V3Controller): # `auth_context` is an instance of AuthContext is extra insurance and # will prevent regressions. - if not isinstance(auth_context, AuthContext): + if not isinstance(auth_context, core.AuthContext): LOG.error( _LE('`auth_context` passed to the Auth controller ' '`authenticate` method is not of type ' diff --git a/keystone/auth/core.py b/keystone/auth/core.py index dd6ed2d829..29a8fac349 100644 --- a/keystone/auth/core.py +++ b/keystone/auth/core.py @@ -10,6 +10,8 @@ # License for the specific language governing permissions and limitations # under the License. +import sys + from oslo_log import log from oslo_log import versionutils from oslo_utils import importutils @@ -17,6 +19,7 @@ import six import stevedore from keystone.common import dependency +from keystone.common import utils import keystone.conf from keystone import exception from keystone.i18n import _, _LI, _LE @@ -77,6 +80,279 @@ def get_auth_method(method_name): return AUTH_METHODS[method_name] +class AuthContext(dict): + """Retrofitting auth_context to reconcile identity attributes. + + The identity attributes must not have conflicting values among the + auth plug-ins. The only exception is `expires_at`, which is set to its + earliest value. + + """ + + # identity attributes need to be reconciled among the auth plugins + IDENTITY_ATTRIBUTES = frozenset(['user_id', 'project_id', + 'access_token_id', 'domain_id', + 'expires_at']) + + def __setitem__(self, key, val): + """Override __setitem__ to prevent conflicting values.""" + if key in self.IDENTITY_ATTRIBUTES and key in self: + existing_val = self[key] + if key == 'expires_at': + # special treatment for 'expires_at', we are going to take + # the earliest expiration instead. + if existing_val != val: + LOG.info(_LI('"expires_at" has conflicting values ' + '%(existing)s and %(new)s. Will use the ' + 'earliest value.'), + {'existing': existing_val, 'new': val}) + if existing_val is None or val is None: + val = existing_val or val + else: + val = min(existing_val, val) + elif existing_val != val: + msg = _('Unable to reconcile identity attribute %(attribute)s ' + 'as it has conflicting values %(new)s and %(old)s') % ( + {'attribute': key, + 'new': val, + 'old': existing_val}) + raise exception.Unauthorized(msg) + return super(AuthContext, self).__setitem__(key, val) + + def update(self, E=None, **F): + """Override update to prevent conflicting values.""" + # NOTE(notmorgan): This will not be nearly as performant as the + # use of the built-in "update" method on the dict, however, the + # volume of data being changed here is very minimal in most cases + # and should not see a significant impact by iterating instead of + # explicit setting of values. + update_dicts = (E or {}, F or {}) + for d in update_dicts: + for key, val in d.items(): + self[key] = val + + +@dependency.requires('resource_api', 'trust_api') +class AuthInfo(object): + """Encapsulation of "auth" request.""" + + @staticmethod + def create(auth=None, scope_only=False): + auth_info = AuthInfo(auth=auth) + auth_info._validate_and_normalize_auth_data(scope_only) + return auth_info + + def __init__(self, auth=None): + self.auth = auth + self._scope_data = (None, None, None, None) + # self._scope_data is (domain_id, project_id, trust_ref, unscoped) + # project scope: (None, project_id, None, None) + # domain scope: (domain_id, None, None, None) + # trust scope: (None, None, trust_ref, None) + # unscoped: (None, None, None, 'unscoped') + + def _assert_project_is_enabled(self, project_ref): + # ensure the project is enabled + try: + self.resource_api.assert_project_enabled( + project_id=project_ref['id'], + project=project_ref) + except AssertionError as e: + LOG.warning(six.text_type(e)) + six.reraise(exception.Unauthorized, exception.Unauthorized(e), + sys.exc_info()[2]) + + def _assert_domain_is_enabled(self, domain_ref): + try: + self.resource_api.assert_domain_enabled( + domain_id=domain_ref['id'], + domain=domain_ref) + except AssertionError as e: + LOG.warning(six.text_type(e)) + six.reraise(exception.Unauthorized, exception.Unauthorized(e), + sys.exc_info()[2]) + + def _lookup_domain(self, domain_info): + domain_id = domain_info.get('id') + domain_name = domain_info.get('name') + try: + if domain_name: + if (CONF.resource.domain_name_url_safe == 'strict' and + utils.is_not_url_safe(domain_name)): + msg = _('Domain name cannot contain reserved characters.') + LOG.warning(msg) + raise exception.Unauthorized(message=msg) + domain_ref = self.resource_api.get_domain_by_name( + domain_name) + else: + domain_ref = self.resource_api.get_domain(domain_id) + except exception.DomainNotFound as e: + LOG.warning(six.text_type(e)) + raise exception.Unauthorized(e) + self._assert_domain_is_enabled(domain_ref) + return domain_ref + + def _lookup_project(self, project_info): + project_id = project_info.get('id') + project_name = project_info.get('name') + try: + if project_name: + if (CONF.resource.project_name_url_safe == 'strict' and + utils.is_not_url_safe(project_name)): + msg = _('Project name cannot contain reserved characters.') + LOG.warning(msg) + raise exception.Unauthorized(message=msg) + if 'domain' not in project_info: + raise exception.ValidationError(attribute='domain', + target='project') + domain_ref = self._lookup_domain(project_info['domain']) + project_ref = self.resource_api.get_project_by_name( + project_name, domain_ref['id']) + else: + project_ref = self.resource_api.get_project(project_id) + # NOTE(morganfainberg): The _lookup_domain method will raise + # exception.Unauthorized if the domain isn't found or is + # disabled. + self._lookup_domain({'id': project_ref['domain_id']}) + except exception.ProjectNotFound as e: + LOG.warning(six.text_type(e)) + raise exception.Unauthorized(e) + self._assert_project_is_enabled(project_ref) + return project_ref + + def _lookup_trust(self, trust_info): + trust_id = trust_info.get('id') + if not trust_id: + raise exception.ValidationError(attribute='trust_id', + target='trust') + trust = self.trust_api.get_trust(trust_id) + return trust + + def _validate_and_normalize_scope_data(self): + """Validate and normalize scope data.""" + if 'scope' not in self.auth: + return + if sum(['project' in self.auth['scope'], + 'domain' in self.auth['scope'], + 'unscoped' in self.auth['scope'], + 'OS-TRUST:trust' in self.auth['scope']]) != 1: + raise exception.ValidationError( + attribute='project, domain, OS-TRUST:trust or unscoped', + target='scope') + if 'unscoped' in self.auth['scope']: + self._scope_data = (None, None, None, 'unscoped') + return + if 'project' in self.auth['scope']: + project_ref = self._lookup_project(self.auth['scope']['project']) + self._scope_data = (None, project_ref['id'], None, None) + elif 'domain' in self.auth['scope']: + domain_ref = self._lookup_domain(self.auth['scope']['domain']) + self._scope_data = (domain_ref['id'], None, None, None) + elif 'OS-TRUST:trust' in self.auth['scope']: + if not CONF.trust.enabled: + raise exception.Forbidden('Trusts are disabled.') + trust_ref = self._lookup_trust( + self.auth['scope']['OS-TRUST:trust']) + # TODO(ayoung): when trusts support domains, fill in domain data + if trust_ref.get('project_id') is not None: + project_ref = self._lookup_project( + {'id': trust_ref['project_id']}) + self._scope_data = (None, project_ref['id'], trust_ref, None) + else: + self._scope_data = (None, None, trust_ref, None) + + def _validate_auth_methods(self): + # make sure all the method data/payload are provided + for method_name in self.get_method_names(): + if method_name not in self.auth['identity']: + raise exception.ValidationError(attribute=method_name, + target='identity') + + # make sure auth method is supported + for method_name in self.get_method_names(): + if method_name not in AUTH_METHODS: + raise exception.AuthMethodNotSupported() + + def _validate_and_normalize_auth_data(self, scope_only=False): + """Make sure "auth" is valid. + + :param scope_only: If it is True, auth methods will not be + validated but only the scope data. + :type scope_only: boolean + """ + # make sure "auth" exist + if not self.auth: + raise exception.ValidationError(attribute='auth', + target='request body') + + # NOTE(chioleong): Tokenless auth does not provide auth methods, + # we only care about using this method to validate the scope + # information. Therefore, validating the auth methods here is + # insignificant and we can skip it when scope_only is set to + # true. + if scope_only is False: + self._validate_auth_methods() + self._validate_and_normalize_scope_data() + + def get_method_names(self): + """Return the identity method names. + + :returns: list of auth method names + + """ + # Sanitizes methods received in request's body + # Filters out duplicates, while keeping elements' order. + method_names = [] + for method in self.auth['identity']['methods']: + if method not in method_names: + method_names.append(method) + return method_names + + def get_method_data(self, method): + """Get the auth method payload. + + :returns: auth method payload + + """ + if method not in self.auth['identity']['methods']: + raise exception.ValidationError(attribute=method, + target='identity') + return self.auth['identity'][method] + + def get_scope(self): + """Get scope information. + + Verify and return the scoping information. + + :returns: (domain_id, project_id, trust_ref, unscoped). + If scope to a project, (None, project_id, None, None) + will be returned. + If scoped to a domain, (domain_id, None, None, None) + will be returned. + If scoped to a trust, (None, project_id, trust_ref, None), + Will be returned, where the project_id comes from the + trust definition. + If unscoped, (None, None, None, 'unscoped') will be + returned. + + """ + return self._scope_data + + def set_scope(self, domain_id=None, project_id=None, trust=None, + unscoped=None): + """Set scope information.""" + if domain_id and project_id: + msg = _('Scoping to both domain and project is not allowed') + raise ValueError(msg) + if domain_id and trust: + msg = _('Scoping to both domain and trust is not allowed') + raise ValueError(msg) + if project_id and trust: + msg = _('Scoping to both project and trust is not allowed') + raise ValueError(msg) + self._scope_data = (domain_id, project_id, trust, unscoped) + + @dependency.requires('identity_api') class UserMFARulesValidator(object): """Helper object that can validate the MFA Rules.""" diff --git a/keystone/common/tokenless_auth.py b/keystone/common/tokenless_auth.py index 17b4f9b1c2..09ce367e64 100644 --- a/keystone/common/tokenless_auth.py +++ b/keystone/common/tokenless_auth.py @@ -17,7 +17,7 @@ import hashlib from oslo_log import log -from keystone.auth import controllers +from keystone.auth import core from keystone.common import dependency import keystone.conf from keystone import exception @@ -92,7 +92,7 @@ class TokenlessAuthHelper(object): auth['scope'] = self._build_scope_info() # NOTE(chioleong): We'll let AuthInfo validate the scope for us - auth_info = controllers.AuthInfo.create(auth, scope_only=True) + auth_info = core.AuthInfo.create(auth, scope_only=True) return auth_info.get_scope() def get_mapped_user(self, project_id=None, domain_id=None): diff --git a/keystone/tests/unit/test_auth_plugin.py b/keystone/tests/unit/test_auth_plugin.py index 9847105fb3..ca29ae1017 100644 --- a/keystone/tests/unit/test_auth_plugin.py +++ b/keystone/tests/unit/test_auth_plugin.py @@ -62,7 +62,7 @@ class TestAuthPlugin(unit.SQLDriverOverrides, unit.TestCase): auth_data[method_name] = {'test': 'test'} auth_data = {'identity': auth_data} self.assertRaises(exception.AuthMethodNotSupported, - auth.controllers.AuthInfo.create, + auth.core.AuthInfo.create, auth_data) def test_addition_auth_steps(self): @@ -76,8 +76,8 @@ class TestAuthPlugin(unit.SQLDriverOverrides, unit.TestCase): auth_data[METHOD_NAME] = { 'test': 'test'} auth_data = {'identity': auth_data} - auth_info = auth.controllers.AuthInfo.create(auth_data) - auth_context = auth.controllers.AuthContext(extras={}, method_names=[]) + auth_info = auth.core.AuthInfo.create(auth_data) + auth_context = auth.core.AuthContext(extras={}, method_names=[]) try: self.api.authenticate(self.make_request(), auth_info, auth_context) except exception.AdditionalAuthRequired as e: @@ -91,8 +91,8 @@ class TestAuthPlugin(unit.SQLDriverOverrides, unit.TestCase): auth_data[METHOD_NAME] = { 'response': EXPECTED_RESPONSE} auth_data = {'identity': auth_data} - auth_info = auth.controllers.AuthInfo.create(auth_data) - auth_context = auth.controllers.AuthContext(extras={}, method_names=[]) + auth_info = auth.core.AuthInfo.create(auth_data) + auth_context = auth.core.AuthContext(extras={}, method_names=[]) self.api.authenticate(self.make_request(), auth_info, auth_context) self.assertEqual(DEMO_USER_ID, auth_context['user_id']) @@ -101,8 +101,8 @@ class TestAuthPlugin(unit.SQLDriverOverrides, unit.TestCase): auth_data[METHOD_NAME] = { 'response': uuid.uuid4().hex} auth_data = {'identity': auth_data} - auth_info = auth.controllers.AuthInfo.create(auth_data) - auth_context = auth.controllers.AuthContext(extras={}, method_names=[]) + auth_info = auth.core.AuthInfo.create(auth_data) + auth_context = auth.core.AuthContext(extras={}, method_names=[]) self.assertRaises(exception.Unauthorized, self.api.authenticate, self.make_request(), @@ -152,8 +152,8 @@ class TestMapped(unit.TestCase): method_name: {'protocol': method_name}, } } - auth_info = auth.controllers.AuthInfo.create(auth_data) - auth_context = auth.controllers.AuthContext( + auth_info = auth.core.AuthInfo.create(auth_data) + auth_context = auth.core.AuthContext( extras={}, method_names=[], user_id=uuid.uuid4().hex) @@ -171,7 +171,7 @@ class TestMapped(unit.TestCase): auth_data[method_name] = {'protocol': method_name} auth_data = {'identity': auth_data} - auth_context = auth.controllers.AuthContext( + auth_context = auth.core.AuthContext( extras={}, method_names=[], user_id=uuid.uuid4().hex) @@ -181,7 +181,7 @@ class TestMapped(unit.TestCase): with mock.patch.object(auth.plugins.mapped.Mapped, 'authenticate', return_value=None) as authenticate: - auth_info = auth.controllers.AuthInfo.create(auth_data) + auth_info = auth.core.AuthInfo.create(auth_data) request = self.make_request(environ={'REMOTE_USER': 'foo@idp.com'}) self.api.authenticate(request, auth_info, auth_context) # make sure Mapped plugin got invoked with the correct payload diff --git a/keystone/tests/unit/test_v3.py b/keystone/tests/unit/test_v3.py index 4016b66754..5e5b9adf3d 100644 --- a/keystone/tests/unit/test_v3.py +++ b/keystone/tests/unit/test_v3.py @@ -1289,8 +1289,8 @@ class RestfulTestCase(unit.SQLDriverOverrides, rest.RestfulTestCase, if not auth_data: auth_data = self.build_authentication_request( kerberos=kerberos)['auth'] - auth_info = auth.controllers.AuthInfo.create(auth_data) - auth_context = auth.controllers.AuthContext(extras={}, method_names=[]) + auth_info = auth.core.AuthInfo.create(auth_data) + auth_context = auth.core.AuthContext(extras={}, method_names=[]) return self.make_request(environ=environment), auth_info, auth_context diff --git a/keystone/tests/unit/test_v3_auth.py b/keystone/tests/unit/test_v3_auth.py index a6de048b11..fcdd88b42b 100644 --- a/keystone/tests/unit/test_v3_auth.py +++ b/keystone/tests/unit/test_v3_auth.py @@ -216,14 +216,14 @@ class TestAuthInfo(common_auth.AuthTestMixin, testcase.TestCase): auth_data['abc'] = {'test': 'test'} auth_data = {'identity': auth_data} self.assertRaises(exception.AuthMethodNotSupported, - auth.controllers.AuthInfo.create, + auth.core.AuthInfo.create, auth_data) def test_missing_auth_method_data(self): auth_data = {'methods': ['password']} auth_data = {'identity': auth_data} self.assertRaises(exception.ValidationError, - auth.controllers.AuthInfo.create, + auth.core.AuthInfo.create, auth_data) def test_project_name_no_domain(self): @@ -232,7 +232,7 @@ class TestAuthInfo(common_auth.AuthTestMixin, testcase.TestCase): password='test', project_name='abc')['auth'] self.assertRaises(exception.ValidationError, - auth.controllers.AuthInfo.create, + auth.core.AuthInfo.create, auth_data) def test_both_project_and_domain_in_scope(self): @@ -242,7 +242,7 @@ class TestAuthInfo(common_auth.AuthTestMixin, testcase.TestCase): project_name='test', domain_name='test')['auth'] self.assertRaises(exception.ValidationError, - auth.controllers.AuthInfo.create, + auth.core.AuthInfo.create, auth_data) def test_get_method_names_duplicates(self): @@ -252,7 +252,7 @@ class TestAuthInfo(common_auth.AuthTestMixin, testcase.TestCase): password='test')['auth'] auth_data['identity']['methods'] = ['password', 'token', 'password', 'password'] - auth_info = auth.controllers.AuthInfo.create(auth_data) + auth_info = auth.core.AuthInfo.create(auth_data) self.assertEqual(['password', 'token'], auth_info.get_method_names()) @@ -260,7 +260,7 @@ class TestAuthInfo(common_auth.AuthTestMixin, testcase.TestCase): auth_data = self.build_authentication_request( user_id='test', password='test')['auth'] - auth_info = auth.controllers.AuthInfo.create(auth_data) + auth_info = auth.core.AuthInfo.create(auth_data) method_name = uuid.uuid4().hex self.assertRaises(exception.ValidationError, @@ -2291,8 +2291,8 @@ class TokenAPITests(object): auth_data['identity']['methods'] = ["password", "external"] auth_data['identity']['external'] = {} api = auth.controllers.Auth() - auth_info = auth.controllers.AuthInfo(auth_data) - auth_context = auth.controllers.AuthContext(extras={}, methods=[]) + auth_info = auth.core.AuthInfo(auth_data) + auth_context = auth.core.AuthContext(extras={}, methods=[]) self.assertRaises(exception.Unauthorized, api.authenticate, self.make_request(), @@ -4948,7 +4948,7 @@ class TestTrustChain(test_v3.RestfulTestCase): class TestAuthContext(unit.TestCase): def setUp(self): super(TestAuthContext, self).setUp() - self.auth_context = auth.controllers.AuthContext() + self.auth_context = auth.core.AuthContext() def test_pick_lowest_expires_at(self): expires_at_1 = utils.isotime(timeutils.utcnow()) @@ -4960,7 +4960,7 @@ class TestAuthContext(unit.TestCase): self.assertEqual(expires_at_1, self.auth_context['expires_at']) def test_identity_attribute_conflict(self): - for identity_attr in auth.controllers.AuthContext.IDENTITY_ATTRIBUTES: + for identity_attr in auth.core.AuthContext.IDENTITY_ATTRIBUTES: self.auth_context[identity_attr] = uuid.uuid4().hex if identity_attr == 'expires_at': # 'expires_at' is a special case. Will test it in a separate @@ -4973,7 +4973,7 @@ class TestAuthContext(unit.TestCase): uuid.uuid4().hex) def test_identity_attribute_conflict_with_none_value(self): - for identity_attr in auth.controllers.AuthContext.IDENTITY_ATTRIBUTES: + for identity_attr in auth.core.AuthContext.IDENTITY_ATTRIBUTES: self.auth_context[identity_attr] = None if identity_attr == 'expires_at': diff --git a/keystone/tests/unit/token/test_fernet_provider.py b/keystone/tests/unit/token/test_fernet_provider.py index 17a2d0e189..31a555f457 100644 --- a/keystone/tests/unit/token/test_fernet_provider.py +++ b/keystone/tests/unit/token/test_fernet_provider.py @@ -146,7 +146,7 @@ class TestValidate(unit.TestCase): federation_constants.IDENTITY_PROVIDER: identity_provider, federation_constants.PROTOCOL: protocol, } - auth_context = auth.controllers.AuthContext(**auth_context_params) + auth_context = auth.core.AuthContext(**auth_context_params) token_id, token_data_ = self.token_provider_api.issue_token( user_ref['id'], method_names, auth_context=auth_context)