Update plugin to newer DOA model

I originally wrote this plugin using django auth backends. Since then the
plugin model has been merged into DOA.

Change the way we configure auth url, move plugin class, many other things.
This commit is contained in:
Jamie Lennox 2015-03-25 01:05:18 +00:00
parent 882ff0bab1
commit fdd31660dd
4 changed files with 87 additions and 69 deletions

View File

@ -1,60 +0,0 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import os
from keystoneclient import auth
from keystoneclient_kerberos import v3 as v3_kerb_auth
from openstack_auth import base
class _HackedKerbAuth(v3_kerb_auth.Kerberos):
def __init__(self, auth_url, original_auth_url):
self.original_auth_url = original_auth_url
super(_HackedKerbAuth, self).__init__(auth_url=auth_url)
def get_endpoint(self, session, **kwargs):
# NOTE(jamielennox): This is a hack to return the actual AUTH_URL
# rather than the one with the kerberos path, other wise project
# listing tries to work on the kerberized path and will fail.
if kwargs.get('interface') == auth.AUTH_INTERFACE:
return self.original_auth_url
return super(_HackedKerbAuth, self).get_endpoint(session, **kwargs)
class KerberosLogin(base.BaseIdentityAuthentication):
def get_unscoped_plugin(self, request=None, auth_url=None, **kwargs):
if not request:
return None
if self.keystone_version < 3:
return None
ticket = request.environ.get('KRB5CCNAME')
if not ticket:
return None
os.environ['KRB5CCNAME'] = ticket
original_auth_url = auth_url
# FIXME(jamielennox): get this from settings
s = auth_url.split('/')
s.insert(-1, 'krb')
auth_url = '/'.join(s)
return _HackedKerbAuth(auth_url, original_auth_url)

View File

@ -0,0 +1,81 @@
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import logging
import os
from django.conf import settings
from keystoneclient import auth
from keystoneclient_kerberos import v3 as v3_kerb_auth
from openstack_auth import plugin
ENV_NAME = 'KRB5CCNAME'
AUTH_SETTING_NAME = 'KERBEROS_AUTH_URL'
LOG = logging.getLogger(__name__)
class _HackedKerbAuth(v3_kerb_auth.Kerberos):
def __init__(self, auth_url, original_auth_url, ticket):
super(_HackedKerbAuth, self).__init__(auth_url=auth_url)
self.original_auth_url = original_auth_url
self.ticket = ticket
def get_endpoint(self, session, **kwargs):
# NOTE(jamielennox): This is a hack to return the actual AUTH_URL
# rather than the one with the kerberos path, other wise project
# listing tries to work on the kerberized path and will fail.
if kwargs.get('interface') == auth.AUTH_INTERFACE:
return self.original_auth_url
return super(_HackedKerbAuth, self).get_endpoint(session, **kwargs)
def get_auth_ref(self, *args, **kwargs):
# NOTE(jamielennox): The only way to specify a ticket is in the global
# environment. Whilst this shouldn't be an issue as has a process per
# worker we limit so that the ticket is only in ENV for the minimum
# time needed.
os.environ[ENV_NAME] = self.ticket
try:
return super(_HackedKerbAuth, self).get_auth_ref(*args, **kwargs)
finally:
os.environ.pop(ENV_NAME, None)
class Kerberos(plugin.BasePlugin):
def __init__(self, *args, **kwargs):
super(Kerberos, self).__init__(*args, **kwargs)
self.login_url = getattr(settings, AUTH_SETTING_NAME, None)
if not self.login_url:
LOG.warn('Kerberos authentication configured, but no '
'"%s" defined in settings.', AUTH_SETTING_NAME)
def get_plugin(self, request=None, auth_url=None, **kwargs):
if not (request and auth_url):
return None
if self.keystone_version < 3:
return None
if not self.login_url:
return None
ticket = request.environ.get(ENV_NAME)
if not ticket:
return None
return _HackedKerbAuth(self.login_url, auth_url, ticket)

View File

@ -17,5 +17,5 @@ from django.conf.urls import url
urlpatterns = patterns(
'openstack_auth_kerberos.views',
url(r'^kerberos/$', 'kerb_login', name='kerberos_login'),
url(r'^krb/$', 'kerb_login', name='kerberos_login'),
)

View File

@ -17,7 +17,6 @@ import time
from django.conf import settings
from django.contrib import auth
from django.contrib.auth.decorators import login_required # noqa
from django import http as django_http
from django import shortcuts
from django.utils import http
@ -32,12 +31,6 @@ from django.views.decorators.debug import sensitive_post_parameters # noqa
from openstack_auth import user as auth_user
from openstack_auth import utils
try:
is_safe_url = http.is_safe_url
except AttributeError:
is_safe_url = utils.is_safe_url
LOG = logging.getLogger(__name__)
@ -55,6 +48,10 @@ def kerb_login(request):
auth_user.set_session_from_user(request, user)
request.session['last_activity'] = int(time.time())
else:
res = shortcuts.redirect('/l')
# NOTE(jamielennox): If horizon is configured correctly this would
# imply that you got a kerberos ticket however you couldn't be logged
# into keystone. Not much we can do here, throw a 401 so that apache
# will trigger a redirect to form login.
res = django_http.HttpResponse('Unauthorized', status=401)
return res