summaryrefslogtreecommitdiffstats
path: root/keystone-moon/keystone/auth
diff options
context:
space:
mode:
Diffstat (limited to 'keystone-moon/keystone/auth')
-rw-r--r--keystone-moon/keystone/auth/controllers.py63
-rw-r--r--keystone-moon/keystone/auth/plugins/core.py5
-rw-r--r--keystone-moon/keystone/auth/plugins/external.py85
-rw-r--r--keystone-moon/keystone/auth/plugins/mapped.py62
-rw-r--r--keystone-moon/keystone/auth/plugins/oauth1.py6
-rw-r--r--keystone-moon/keystone/auth/plugins/password.py5
-rw-r--r--keystone-moon/keystone/auth/plugins/saml2.py3
-rw-r--r--keystone-moon/keystone/auth/plugins/token.py4
8 files changed, 68 insertions, 165 deletions
diff --git a/keystone-moon/keystone/auth/controllers.py b/keystone-moon/keystone/auth/controllers.py
index 065f1f01..04124696 100644
--- a/keystone-moon/keystone/auth/controllers.py
+++ b/keystone-moon/keystone/auth/controllers.py
@@ -17,16 +17,18 @@ import sys
from keystoneclient.common import cms
from oslo_config import cfg
from oslo_log import log
+from oslo_log import versionutils
from oslo_serialization import jsonutils
from oslo_utils import importutils
-from oslo_utils import timeutils
import six
+import stevedore
from keystone.common import controller
from keystone.common import dependency
+from keystone.common import utils
from keystone.common import wsgi
from keystone import config
-from keystone.contrib import federation
+from keystone.contrib.federation import constants as federation_constants
from keystone import exception
from keystone.i18n import _, _LI, _LW
from keystone.resource import controllers as resource_controllers
@@ -41,6 +43,27 @@ AUTH_METHODS = {}
AUTH_PLUGINS_LOADED = False
+def load_auth_method(method):
+ plugin_name = CONF.auth.get(method) or 'default'
+ try:
+ namespace = 'keystone.auth.%s' % method
+ driver_manager = stevedore.DriverManager(namespace, plugin_name,
+ invoke_on_load=True)
+ return driver_manager.driver
+ except RuntimeError:
+ LOG.debug('Failed to load the %s driver (%s) using stevedore, will '
+ 'attempt to load using import_object instead.',
+ method, plugin_name)
+
+ @versionutils.deprecated(as_of=versionutils.deprecated.LIBERTY,
+ in_favor_of='entrypoints',
+ what='direct import of driver')
+ def _load_using_import(plugin_name):
+ return importutils.import_object(plugin_name)
+
+ return _load_using_import(plugin_name)
+
+
def load_auth_methods():
global AUTH_PLUGINS_LOADED
@@ -50,28 +73,8 @@ def load_auth_methods():
# config.setup_authentication should be idempotent, call it to ensure we
# have setup all the appropriate configuration options we may need.
config.setup_authentication()
- for plugin in CONF.auth.methods:
- if '.' in plugin:
- # NOTE(morganfainberg): if '.' is in the plugin name, it should be
- # imported rather than used as a plugin identifier.
- plugin_class = plugin
- driver = importutils.import_object(plugin)
- if not hasattr(driver, 'method'):
- raise ValueError(_('Cannot load an auth-plugin by class-name '
- 'without a "method" attribute defined: %s'),
- plugin_class)
-
- LOG.info(_LI('Loading auth-plugins by class-name is deprecated.'))
- plugin_name = driver.method
- else:
- plugin_name = plugin
- plugin_class = CONF.auth.get(plugin)
- driver = importutils.import_object(plugin_class)
- if plugin_name in AUTH_METHODS:
- raise ValueError(_('Auth plugin %(plugin)s is requesting '
- 'previously registered method %(method)s') %
- {'plugin': plugin_class, 'method': driver.method})
- AUTH_METHODS[plugin_name] = driver
+ for plugin in set(CONF.auth.methods):
+ AUTH_METHODS[plugin] = load_auth_method(plugin)
AUTH_PLUGINS_LOADED = True
@@ -121,11 +124,7 @@ class AuthContext(dict):
return super(AuthContext, self).__setitem__(key, val)
-# TODO(blk-u): this class doesn't use identity_api directly, but makes it
-# available for consumers. Consumers should probably not be getting
-# identity_api from this since it's available in global registry, then
-# identity_api should be removed from this list.
-@dependency.requires('identity_api', 'resource_api', 'trust_api')
+@dependency.requires('resource_api', 'trust_api')
class AuthInfo(object):
"""Encapsulation of "auth" request."""
@@ -217,8 +216,6 @@ class AuthInfo(object):
raise exception.ValidationError(attribute='trust_id',
target='trust')
trust = self.trust_api.get_trust(trust_id)
- if not trust:
- raise exception.TrustNotFound(trust_id=trust_id)
return trust
def _validate_and_normalize_scope_data(self):
@@ -415,7 +412,7 @@ class Auth(controller.V3Controller):
return
# Skip scoping when unscoped federated token is being issued
- if federation.IDENTITY_PROVIDER in auth_context:
+ if federation_constants.IDENTITY_PROVIDER in auth_context:
return
# Do not scope if request is for explicitly unscoped token
@@ -546,7 +543,7 @@ class Auth(controller.V3Controller):
for t in tokens:
expires = t['expires']
if not (expires and isinstance(expires, six.text_type)):
- t['expires'] = timeutils.isotime(expires)
+ t['expires'] = utils.isotime(expires)
data = {'revoked': tokens}
json_data = jsonutils.dumps(data)
signed_text = cms.cms_sign_text(json_data,
diff --git a/keystone-moon/keystone/auth/plugins/core.py b/keystone-moon/keystone/auth/plugins/core.py
index 96a5ecf8..bcad27e5 100644
--- a/keystone-moon/keystone/auth/plugins/core.py
+++ b/keystone-moon/keystone/auth/plugins/core.py
@@ -21,6 +21,7 @@ import six
from keystone.common import dependency
from keystone import exception
+
CONF = cfg.CONF
LOG = log.getLogger(__name__)
@@ -51,7 +52,7 @@ def convert_method_list_to_integer(methods):
method_ints = []
for method in methods:
- for k, v in six.iteritems(method_map):
+ for k, v in method_map.items():
if v == method:
method_ints.append(k)
return sum(method_ints)
@@ -71,7 +72,7 @@ def convert_integer_to_method_list(method_int):
method_map = construct_method_map_from_config()
method_ints = []
- for k, v in six.iteritems(method_map):
+ for k, v in method_map.items():
method_ints.append(k)
method_ints.sort(reverse=True)
diff --git a/keystone-moon/keystone/auth/plugins/external.py b/keystone-moon/keystone/auth/plugins/external.py
index 2322649f..cabe6282 100644
--- a/keystone-moon/keystone/auth/plugins/external.py
+++ b/keystone-moon/keystone/auth/plugins/external.py
@@ -23,7 +23,6 @@ from keystone import auth
from keystone.common import dependency
from keystone import exception
from keystone.i18n import _
-from keystone.openstack.common import versionutils
CONF = cfg.CONF
@@ -31,9 +30,6 @@ CONF = cfg.CONF
@six.add_metaclass(abc.ABCMeta)
class Base(auth.AuthMethodHandler):
-
- method = 'external'
-
def authenticate(self, context, auth_info, auth_context):
"""Use REMOTE_USER to look up the user in the identity backend.
@@ -96,91 +92,10 @@ class Domain(Base):
return user_ref
-@dependency.requires('assignment_api', 'identity_api')
class KerberosDomain(Domain):
"""Allows `kerberos` as a method."""
- method = 'kerberos'
-
def _authenticate(self, remote_user, context):
auth_type = context['environment'].get('AUTH_TYPE')
if auth_type != 'Negotiate':
raise exception.Unauthorized(_("auth_type is not Negotiate"))
return super(KerberosDomain, self)._authenticate(remote_user, context)
-
-
-class ExternalDefault(DefaultDomain):
- """Deprecated. Please use keystone.auth.external.DefaultDomain instead."""
-
- @versionutils.deprecated(
- as_of=versionutils.deprecated.ICEHOUSE,
- in_favor_of='keystone.auth.external.DefaultDomain',
- remove_in=+1)
- def __init__(self):
- super(ExternalDefault, self).__init__()
-
-
-class ExternalDomain(Domain):
- """Deprecated. Please use keystone.auth.external.Domain instead."""
-
- @versionutils.deprecated(
- as_of=versionutils.deprecated.ICEHOUSE,
- in_favor_of='keystone.auth.external.Domain',
- remove_in=+1)
- def __init__(self):
- super(ExternalDomain, self).__init__()
-
-
-@dependency.requires('identity_api')
-class LegacyDefaultDomain(Base):
- """Deprecated. Please use keystone.auth.external.DefaultDomain instead.
-
- This plugin exists to provide compatibility for the unintended behavior
- described here: https://bugs.launchpad.net/keystone/+bug/1253484
-
- """
-
- @versionutils.deprecated(
- as_of=versionutils.deprecated.ICEHOUSE,
- in_favor_of='keystone.auth.external.DefaultDomain',
- remove_in=+1)
- def __init__(self):
- super(LegacyDefaultDomain, self).__init__()
-
- def _authenticate(self, remote_user, context):
- """Use remote_user to look up the user in the identity backend."""
- # NOTE(dolph): this unintentionally discards half the REMOTE_USER value
- names = remote_user.split('@')
- username = names.pop(0)
- domain_id = CONF.identity.default_domain_id
- user_ref = self.identity_api.get_user_by_name(username, domain_id)
- return user_ref
-
-
-@dependency.requires('identity_api', 'resource_api')
-class LegacyDomain(Base):
- """Deprecated. Please use keystone.auth.external.Domain instead."""
-
- @versionutils.deprecated(
- as_of=versionutils.deprecated.ICEHOUSE,
- in_favor_of='keystone.auth.external.Domain',
- remove_in=+1)
- def __init__(self):
- super(LegacyDomain, self).__init__()
-
- def _authenticate(self, remote_user, context):
- """Use remote_user to look up the user in the identity backend.
-
- If remote_user contains an `@` assume that the substring before the
- rightmost `@` is the username, and the substring after the @ is the
- domain name.
- """
- names = remote_user.rsplit('@', 1)
- username = names.pop(0)
- if names:
- domain_name = names[0]
- domain_ref = self.resource_api.get_domain_by_name(domain_name)
- domain_id = domain_ref['id']
- else:
- domain_id = CONF.identity.default_domain_id
- user_ref = self.identity_api.get_user_by_name(username, domain_id)
- return user_ref
diff --git a/keystone-moon/keystone/auth/plugins/mapped.py b/keystone-moon/keystone/auth/plugins/mapped.py
index abf44481..220ff013 100644
--- a/keystone-moon/keystone/auth/plugins/mapped.py
+++ b/keystone-moon/keystone/auth/plugins/mapped.py
@@ -13,14 +13,13 @@
import functools
from oslo_log import log
-from oslo_serialization import jsonutils
from pycadf import cadftaxonomy as taxonomy
from six.moves.urllib import parse
from keystone import auth
from keystone.auth import plugins as auth_plugins
from keystone.common import dependency
-from keystone.contrib import federation
+from keystone.contrib.federation import constants as federation_constants
from keystone.contrib.federation import utils
from keystone import exception
from keystone.i18n import _
@@ -33,8 +32,8 @@ LOG = log.getLogger(__name__)
METHOD_NAME = 'mapped'
-@dependency.requires('assignment_api', 'federation_api', 'identity_api',
- 'token_provider_api')
+@dependency.requires('federation_api', 'identity_api',
+ 'resource_api', 'token_provider_api')
class Mapped(auth.AuthMethodHandler):
def _get_token_ref(self, auth_payload):
@@ -44,7 +43,7 @@ class Mapped(auth.AuthMethodHandler):
token_data=response)
def authenticate(self, context, auth_payload, auth_context):
- """Authenticate mapped user and return an authentication context.
+ """Authenticate mapped user and set an authentication context.
:param context: keystone's request context
:param auth_payload: the content of the authentication for a
@@ -66,7 +65,7 @@ class Mapped(auth.AuthMethodHandler):
self.token_provider_api)
else:
handle_unscoped_token(context, auth_payload, auth_context,
- self.assignment_api, self.federation_api,
+ self.resource_api, self.federation_api,
self.identity_api)
@@ -101,12 +100,12 @@ def handle_scoped_token(context, auth_payload, auth_context, token_ref,
auth_context['user_id'] = user_id
auth_context['group_ids'] = group_ids
- auth_context[federation.IDENTITY_PROVIDER] = identity_provider
- auth_context[federation.PROTOCOL] = protocol
+ auth_context[federation_constants.IDENTITY_PROVIDER] = identity_provider
+ auth_context[federation_constants.PROTOCOL] = protocol
def handle_unscoped_token(context, auth_payload, auth_context,
- assignment_api, federation_api, identity_api):
+ resource_api, federation_api, identity_api):
def is_ephemeral_user(mapped_properties):
return mapped_properties['user']['type'] == utils.UserType.EPHEMERAL
@@ -115,8 +114,9 @@ def handle_unscoped_token(context, auth_payload, auth_context,
identity_provider, protocol):
auth_context['user_id'] = user['id']
auth_context['group_ids'] = mapped_properties['group_ids']
- auth_context[federation.IDENTITY_PROVIDER] = identity_provider
- auth_context[federation.PROTOCOL] = protocol
+ auth_context[federation_constants.IDENTITY_PROVIDER] = (
+ identity_provider)
+ auth_context[federation_constants.PROTOCOL] = protocol
def build_local_user_context(auth_context, mapped_properties):
user_info = auth_plugins.UserAuthInfo.create(mapped_properties,
@@ -139,17 +139,15 @@ def handle_unscoped_token(context, auth_payload, auth_context,
user_id = None
try:
- mapped_properties = apply_mapping_filter(
- identity_provider, protocol, assertion, assignment_api,
+ mapped_properties, mapping_id = apply_mapping_filter(
+ identity_provider, protocol, assertion, resource_api,
federation_api, identity_api)
if is_ephemeral_user(mapped_properties):
user = setup_username(context, mapped_properties)
user_id = user['id']
group_ids = mapped_properties['group_ids']
- mapping = federation_api.get_mapping_from_idp_and_protocol(
- identity_provider, protocol)
- utils.validate_groups_cardinality(group_ids, mapping['id'])
+ utils.validate_groups_cardinality(group_ids, mapping_id)
build_ephemeral_user_context(auth_context, user,
mapped_properties,
identity_provider, protocol)
@@ -182,32 +180,29 @@ def extract_assertion_data(context):
def apply_mapping_filter(identity_provider, protocol, assertion,
- assignment_api, federation_api, identity_api):
+ resource_api, federation_api, identity_api):
idp = federation_api.get_idp(identity_provider)
- utils.validate_idp(idp, assertion)
- mapping = federation_api.get_mapping_from_idp_and_protocol(
- identity_provider, protocol)
- rules = jsonutils.loads(mapping['rules'])
- LOG.debug('using the following rules: %s', rules)
- rule_processor = utils.RuleProcessor(rules)
- mapped_properties = rule_processor.process(assertion)
+ utils.validate_idp(idp, protocol, assertion)
+
+ mapped_properties, mapping_id = federation_api.evaluate(
+ identity_provider, protocol, assertion)
# NOTE(marek-denis): We update group_ids only here to avoid fetching
# groups identified by name/domain twice.
# NOTE(marek-denis): Groups are translated from name/domain to their
# corresponding ids in the auth plugin, as we need information what
- # ``mapping_id`` was used as well as idenity_api and assignment_api
+ # ``mapping_id`` was used as well as idenity_api and resource_api
# objects.
group_ids = mapped_properties['group_ids']
utils.validate_groups_in_backend(group_ids,
- mapping['id'],
+ mapping_id,
identity_api)
group_ids.extend(
utils.transform_to_group_ids(
- mapped_properties['group_names'], mapping['id'],
- identity_api, assignment_api))
+ mapped_properties['group_names'], mapping_id,
+ identity_api, resource_api))
mapped_properties['group_ids'] = list(set(group_ids))
- return mapped_properties
+ return mapped_properties, mapping_id
def setup_username(context, mapped_properties):
@@ -241,12 +236,17 @@ def setup_username(context, mapped_properties):
user_name = user.get('name') or context['environment'].get('REMOTE_USER')
if not any([user_id, user_name]):
- raise exception.Unauthorized(_("Could not map user"))
+ msg = _("Could not map user while setting ephemeral user identity. "
+ "Either mapping rules must specify user id/name or "
+ "REMOTE_USER environment variable must be set.")
+ raise exception.Unauthorized(msg)
elif not user_name:
user['name'] = user_id
elif not user_id:
- user['id'] = parse.quote(user_name)
+ user_id = user_name
+
+ user['id'] = parse.quote(user_id)
return user
diff --git a/keystone-moon/keystone/auth/plugins/oauth1.py b/keystone-moon/keystone/auth/plugins/oauth1.py
index 2f1cc2fa..e081cd62 100644
--- a/keystone-moon/keystone/auth/plugins/oauth1.py
+++ b/keystone-moon/keystone/auth/plugins/oauth1.py
@@ -29,15 +29,9 @@ LOG = log.getLogger(__name__)
@dependency.requires('oauth_api')
class OAuth(auth.AuthMethodHandler):
-
- method = 'oauth1'
-
def authenticate(self, context, auth_info, auth_context):
"""Turn a signed request with an access key into a keystone token."""
- if not self.oauth_api:
- raise exception.Unauthorized(_('%s not supported') % self.method)
-
headers = context['headers']
oauth_headers = oauth.get_oauth_headers(headers)
access_token_id = oauth_headers.get('oauth_token')
diff --git a/keystone-moon/keystone/auth/plugins/password.py b/keystone-moon/keystone/auth/plugins/password.py
index c5770445..16492a32 100644
--- a/keystone-moon/keystone/auth/plugins/password.py
+++ b/keystone-moon/keystone/auth/plugins/password.py
@@ -20,6 +20,7 @@ from keystone.common import dependency
from keystone import exception
from keystone.i18n import _
+
METHOD_NAME = 'password'
LOG = log.getLogger(__name__)
@@ -28,11 +29,9 @@ LOG = log.getLogger(__name__)
@dependency.requires('identity_api')
class Password(auth.AuthMethodHandler):
- method = METHOD_NAME
-
def authenticate(self, context, auth_payload, auth_context):
"""Try to authenticate against the identity backend."""
- user_info = auth_plugins.UserAuthInfo.create(auth_payload, self.method)
+ user_info = auth_plugins.UserAuthInfo.create(auth_payload, METHOD_NAME)
# FIXME(gyee): identity.authenticate() can use some refactoring since
# all we care is password matches
diff --git a/keystone-moon/keystone/auth/plugins/saml2.py b/keystone-moon/keystone/auth/plugins/saml2.py
index 744f26a9..cf7a8a50 100644
--- a/keystone-moon/keystone/auth/plugins/saml2.py
+++ b/keystone-moon/keystone/auth/plugins/saml2.py
@@ -23,5 +23,4 @@ This plugin subclasses mapped.Mapped, and may be specified in keystone.conf:
class Saml2(mapped.Mapped):
-
- method = 'saml2'
+ pass
diff --git a/keystone-moon/keystone/auth/plugins/token.py b/keystone-moon/keystone/auth/plugins/token.py
index 5ca0b257..069f1140 100644
--- a/keystone-moon/keystone/auth/plugins/token.py
+++ b/keystone-moon/keystone/auth/plugins/token.py
@@ -33,8 +33,6 @@ CONF = cfg.CONF
@dependency.requires('federation_api', 'identity_api', 'token_provider_api')
class Token(auth.AuthMethodHandler):
- method = 'token'
-
def _get_token_ref(self, auth_payload):
token_id = auth_payload['id']
response = self.token_provider_api.validate_token(token_id)
@@ -44,7 +42,7 @@ class Token(auth.AuthMethodHandler):
def authenticate(self, context, auth_payload, user_context):
if 'id' not in auth_payload:
raise exception.ValidationError(attribute='id',
- target=self.method)
+ target='token')
token_ref = self._get_token_ref(auth_payload)
if token_ref.is_federated_user and self.federation_api:
mapped.handle_scoped_token(