summaryrefslogtreecommitdiffstats
path: root/keystone/auth
diff options
context:
space:
mode:
authorAdam Young <ayoung@redhat.com>2013-07-12 10:23:38 -0400
committerJamie Lennox <jamielennox@gmail.com>2013-07-17 12:45:52 +1000
commit88c319e6bce98082f9a90b8b27726793d5366326 (patch)
tree867ae6600cec6cfd50885eaf86d17dfb27cd1a16 /keystone/auth
parent3a56c8a68d0f033266f98963261a6d724e506966 (diff)
downloadkeystone-88c319e6bce98082f9a90b8b27726793d5366326.tar.gz
keystone-88c319e6bce98082f9a90b8b27726793d5366326.tar.xz
keystone-88c319e6bce98082f9a90b8b27726793d5366326.zip
Pluggable Remote User
Select the code to handle REMOTE_USER based on a config file option Fixes the REMOTE_USER logic to get the domain name from REALM, which is the least surprise option. Disregards the auth_data passed in, as we should be using REMOTE_USER to get the user name. External Plugin is now executed in conjunction with the auth methods, as opposed to in place of them. DocImpact blueprint pluggable-remote-user Change-Id: I9dda6dbe073f03806bdf539db6faa01644109f1c
Diffstat (limited to 'keystone/auth')
-rw-r--r--keystone/auth/controllers.py22
-rw-r--r--keystone/auth/plugins/external.py80
2 files changed, 82 insertions, 20 deletions
diff --git a/keystone/auth/controllers.py b/keystone/auth/controllers.py
index 47c44b03..cc4c1605 100644
--- a/keystone/auth/controllers.py
+++ b/keystone/auth/controllers.py
@@ -321,31 +321,13 @@ class Auth(controller.V3Controller):
LOG.exception(e)
raise exception.Unauthorized(e)
- def _build_remote_user_auth_context(self, context, auth_info,
- auth_context):
- username = context['REMOTE_USER']
- # FIXME(gyee): REMOTE_USER is not good enough since we are
- # requiring domain_id to do user lookup now. Try to get
- # the user_id from auth_info for now, assuming external auth
- # has check to make sure user is the same as the one specify
- # in "identity".
- if 'password' in auth_info.get_method_names():
- user_info = auth_info.get_method_data('password')
- user_ref = auth_info.lookup_user(user_info['user'])
- auth_context['user_id'] = user_ref['id']
- else:
- msg = _('Unable to lookup user %s') % (username)
- raise exception.Unauthorized(msg)
-
def authenticate(self, context, auth_info, auth_context):
"""Authenticate user."""
# user have been authenticated externally
if 'REMOTE_USER' in context:
- self._build_remote_user_auth_context(context,
- auth_info,
- auth_context)
- return
+ external = get_auth_method('external')
+ external.authenticate(context, auth_info, auth_context)
# need to aggregate the results in case two or more methods
# are specified
diff --git a/keystone/auth/plugins/external.py b/keystone/auth/plugins/external.py
new file mode 100644
index 00000000..3460ab92
--- /dev/null
+++ b/keystone/auth/plugins/external.py
@@ -0,0 +1,80 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2013 OpenStack LLC
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+"""Keystone External Authentication Plugin"""
+
+from keystone.common import config
+from keystone import exception
+
+
+CONF = config.CONF
+
+
+class ExternalDefault(object):
+ def authenticate(self, context, auth_info, auth_context):
+ """Use REMOTE_USER to look up the user in the identity backend
+
+ auth_context is an in-out variable that will be updated with the
+ username from the REMOTE_USER environment variable.
+ """
+ try:
+ REMOTE_USER = context['REMOTE_USER']
+ except KeyError:
+ msg = _('No authenticated user')
+ raise exception.Unauthorized(msg)
+ try:
+ names = REMOTE_USER.split('@')
+ username = names.pop(0)
+ domain_id = CONF.identity.default_domain_id
+ user_ref = auth_info.identity_api.get_user_by_name(username,
+ domain_id)
+ auth_context['user_id'] = user_ref['id']
+ except Exception:
+ msg = _('Unable to lookup user %s') % (REMOTE_USER)
+ raise exception.Unauthorized(msg)
+
+
+class ExternalDomain(object):
+ def authenticate(self, context, auth_info, auth_context):
+ """Use REMOTE_USER to look up the user in the identity backend
+
+ auth_context is an in-out variable that will be updated with the
+ username from the REMOTE_USER environment variable.
+
+ If REMOTE_USER contains an `@` assume that the substring before the @
+ is the username, and the substring after the @ is the domain name.
+ """
+ try:
+ REMOTE_USER = context['REMOTE_USER']
+ except KeyError:
+ msg = _('No authenticated user')
+ raise exception.Unauthorized(msg)
+ try:
+ names = REMOTE_USER.split('@')
+ username = names.pop(0)
+ if names:
+ domain_name = names[0]
+ domain_ref = (auth_info.identity_api.
+ get_domain_by_name(domain_name))
+ domain_id = domain_ref['id']
+ else:
+ domain_id = CONF.identity.default_domain_id
+ user_ref = auth_info.identity_api.get_user_by_name(username,
+ domain_id)
+ auth_context['user_id'] = user_ref['id']
+ except Exception:
+ msg = _('Unable to lookup user %s') % (REMOTE_USER)
+ raise exception.Unauthorized(msg)