diff options
-rw-r--r-- | freeipa.spec.in | 1 | ||||
-rw-r--r-- | install/conf/ipa.conf | 23 | ||||
-rw-r--r-- | install/share/wsgi.py | 3 | ||||
-rw-r--r-- | install/ui/ipa.js | 3 | ||||
-rw-r--r-- | ipalib/backend.py | 5 | ||||
-rw-r--r-- | ipalib/krb_utils.py | 71 | ||||
-rw-r--r-- | ipalib/session.py | 126 | ||||
-rw-r--r-- | ipaserver/plugins/xmlserver.py | 7 | ||||
-rw-r--r-- | ipaserver/rpcserver.py | 253 | ||||
-rwxr-xr-x | lite-server.py | 2 | ||||
-rwxr-xr-x | make-lint | 2 | ||||
-rw-r--r-- | tests/test_ipaserver/test_rpcserver.py | 6 |
12 files changed, 376 insertions, 126 deletions
diff --git a/freeipa.spec.in b/freeipa.spec.in index 3e9db73b1..3609bddf0 100644 --- a/freeipa.spec.in +++ b/freeipa.spec.in @@ -74,6 +74,7 @@ BuildRequires: python-rhsm BuildRequires: pyOpenSSL BuildRequires: pylint BuildRequires: libipa_hbac-python +BuildRequires: python-memcached %description IPA is an integrated solution to provide centrally managed Identity (machine, diff --git a/install/conf/ipa.conf b/install/conf/ipa.conf index 676086a90..cd806be7d 100644 --- a/install/conf/ipa.conf +++ b/install/conf/ipa.conf @@ -44,8 +44,8 @@ WSGIScriptReloading Off KrbConstrainedDelegationLock ipa -# Protect UI login url with Kerberos -<Location "/ipa/login"> +# Protect /ipa and everything below it in webspace with Apache Kerberos auth +<Location "/ipa"> AuthType Kerberos AuthName "Kerberos Login" KrbMethodNegotiate on @@ -59,22 +59,13 @@ KrbConstrainedDelegationLock ipa ErrorDocument 401 /ipa/errors/unauthorized.html </Location> -# Protect xmlrpc url with Kerberos -<Location "/ipa/xml"> - AuthType Kerberos - AuthName "Kerberos Login" - KrbMethodNegotiate on - KrbMethodK5Passwd off - KrbServiceName HTTP - KrbAuthRealms $REALM - Krb5KeyTab /etc/httpd/conf/ipa.keytab - KrbSaveCredentials on - KrbConstrainedDelegation on - Require valid-user - ErrorDocument 401 /ipa/errors/unauthorized.html +# Turn off Apache authentication for sessions +<Location "/ipa/session"> + Satisfy Any + Order Deny,Allow + Allow from all </Location> - # This is where we redirect on failed auth Alias /ipa/errors "/usr/share/ipa/html" diff --git a/install/share/wsgi.py b/install/share/wsgi.py index b61b919da..9f7d3f487 100644 --- a/install/share/wsgi.py +++ b/install/share/wsgi.py @@ -1,6 +1,7 @@ # Authors: # Rob Crittenden <rcritten@redhat.com> # Jason Gerard DeRose <jderose@redhat.com> +# John Dennis <jdennis@redhat.com> # # Copyright (C) 2010 Red Hat # see file 'COPYING' for use and warranty information @@ -45,6 +46,6 @@ else: # This is the WSGI callable: def application(environ, start_response): if not environ['wsgi.multithread']: - return api.Backend.session(environ, start_response) + return api.Backend.wsgi_dispatch(environ, start_response) else: api.log.error("IPA does not work with the threaded MPM, use the pre-fork MPM") diff --git a/install/ui/ipa.js b/install/ui/ipa.js index 82e892043..a599f6a8c 100644 --- a/install/ui/ipa.js +++ b/install/ui/ipa.js @@ -3,6 +3,7 @@ * Pavel Zuna <pzuna@redhat.com> * Adam Young <ayoung@redhat.com> * Endi Dewata <edewata@redhat.com> + * John Dennis <jdennis@redhat.com> * * Copyright (C) 2010 Red Hat * see file 'COPYING' for use and warranty information @@ -58,7 +59,7 @@ var IPA = function() { // if current path matches live server path, use live data if (that.url && window.location.pathname.substring(0, that.url.length) === that.url) { - that.json_url = params.url || '/ipa/json'; + that.json_url = params.url || '/ipa/session/json'; that.login_url = params.url || '/ipa/login'; } else { // otherwise use fixtures diff --git a/ipalib/backend.py b/ipalib/backend.py index 7ed378e88..0232fa536 100644 --- a/ipalib/backend.py +++ b/ipalib/backend.py @@ -23,6 +23,7 @@ Base classes for all backed-end plugins. import threading import plugable +import os from errors import PublicError, InternalError, CommandError from request import context, Connection, destroy_context @@ -106,6 +107,10 @@ class Executioner(Backend): """ client_ip: The IP address of the remote client. """ + + if ccache is not None: + os.environ["KRB5CCNAME"] = ccache + if self.env.in_server: self.Backend.ldap2.connect(ccache=ccache) else: diff --git a/ipalib/krb_utils.py b/ipalib/krb_utils.py index e04c70ae7..21bca68a6 100644 --- a/ipalib/krb_utils.py +++ b/ipalib/krb_utils.py @@ -158,7 +158,6 @@ class KRB5_CCache(object): self.ccache = None self.principal = None - self.debug('opening ccache file "%s"', ccache) try: self.context = krbV.default_context() self.scheme, self.name = krb5_parse_ccache(ccache) @@ -228,8 +227,6 @@ class KRB5_CCache(object): except krbV.Krb5Error, e: error_code = e.args[0] if error_code == KRB5_CC_NOTFOUND: - self.debug('"%s" credential not found in "%s" ccache', - krbV_principal.name, self.ccache_str()) #pylint: disable=E1103 raise KeyError('"%s" credential not found in "%s" ccache' % \ (krbV_principal.name, self.ccache_str())) #pylint: disable=E1103 raise e @@ -281,7 +278,7 @@ class KRB5_CCache(object): cred = self.get_credentials(krbV_principal) authtime, starttime, endtime, renew_till = cred[3] - self.debug('principal=%s, authtime=%s, starttime=%s, endtime=%s, renew_till=%s', + self.debug('get_credential_times: principal=%s, authtime=%s, starttime=%s, endtime=%s, renew_till=%s', krbV_principal.name, #pylint: disable=E1103 krb5_format_time(authtime), krb5_format_time(starttime), krb5_format_time(endtime), krb5_format_time(renew_till)) @@ -327,3 +324,69 @@ class KRB5_CCache(object): if endtime < now: return False return True + + def valid(self, host, realm): + ''' + Test to see if ldap service ticket or the TGT is valid. + + :parameters: + host + ldap server + realm + kerberos realm + :returns: + True if either the ldap service ticket or the TGT is valid, + False otherwise. + ''' + + try: + principal = krb5_format_service_principal_name('ldap', host, realm) + valid = self.credential_is_valid(principal) + if valid: + return True + except KeyError: + pass + + try: + principal = krb5_format_tgt_principal_name(realm) + valid = self.credential_is_valid(principal) + return valid + except KeyError: + return False + + def endtime(self, host, realm): + ''' + Returns the minimum endtime for tickets of interest (ldap service or TGT). + + :parameters: + host + ldap server + realm + kerberos realm + :returns: + UNIX timestamp value. + ''' + + result = 0 + try: + principal = krb5_format_service_principal_name('ldap', host, realm) + authtime, starttime, endtime, renew_till = self.get_credential_times(principal) + if result: + result = min(result, endtime) + else: + result = endtime + except KeyError: + pass + + try: + principal = krb5_format_tgt_principal_name(realm) + authtime, starttime, endtime, renew_till = self.get_credential_times(principal) + if result: + result = min(result, endtime) + else: + result = endtime + except KeyError: + pass + + self.debug('"%s" ccache endtime=%s', self.ccache_str(), krb5_format_time(result)) + return result diff --git a/ipalib/session.py b/ipalib/session.py index a58643983..1f5ee379d 100644 --- a/ipalib/session.py +++ b/ipalib/session.py @@ -25,6 +25,8 @@ import re import time from text import _ from ipapython.ipa_log_manager import * +from ipalib import api, errors +from ipalib import Command from ipalib.krb_utils import * __doc__ = ''' @@ -632,6 +634,82 @@ def fmt_time(timestamp): #------------------------------------------------------------------------------- +class AuthManager(object): + ''' + This class is an abstract base class and is meant to be subclassed + to provide actual functionality. The purpose is to encapsulate all + the callbacks one might need to manage authenticaion. Different + authentication mechanisms will instantiate a subclass of this and + register it with the SessionAuthManger. When an authentication + event occurs the matching method will be called for each + registered class. This allows the SessionAuthManager to notify + interested parties. + ''' + + def __init__(self, name): + log_mgr.get_logger(self, True) + self.name = name + + + def logout(self, session_data): + ''' + Called when a user requests to be logged out of their session. + + :parameters: + session_data + The current session data + :returns: + None + ''' + self.debug('AuthManager.logout.%s:', self.name) + +class SessionAuthManager(object): + ''' + ''' + + def __init__(self): + ''' + ''' + log_mgr.get_logger(self, True) + self.auth_managers = {} + + def register(self, name, auth_mgr): + self.debug('SessionAuthManager.register: name=%s', name) + + existing_mgr = self.auth_managers.get(name) + if existing_mgr is not None: + raise KeyError('cannot register auth manager named "%s" one already exists, name="%s" object=%s', + name, existing_mgr.name, repr(existing_mgr)) + + if not isinstance(auth_mgr, AuthManager): + raise TypeError('auth_mgr must be an instance of AuthManager, not %s', + auth_mgr.__class__.__name__) + + self.auth_managers[name] = auth_mgr + + + def unregister(self, name): + self.debug('SessionAuthManager.unregister: name=%s', name) + + if not self.auth_managers.has_key(name): + raise KeyError('cannot unregister auth manager named "%s", does not exist', + name) + del self.auth_managers[name] + + + def logout(self, session_data): + ''' + ''' + self.debug('SessionAuthManager.logout:') + + for auth_mgr in self.auth_managers.values(): + try: + auth_mgr.logout(session_data) + except Exception, e: + self.error('%s auth_mgr logout failed: %s', auth_mgr.name, e) + +#------------------------------------------------------------------------------- + class SessionManager(object): ''' @@ -649,8 +727,9 @@ class SessionManager(object): log_mgr.get_logger(self, True) self.generated_session_ids = set() + self.auth_mgr = SessionAuthManager() - def generate_session_id(self, n_bits=48): + def generate_session_id(self, n_bits=128): ''' Return a random string to be used as a session id. @@ -790,8 +869,7 @@ class MemcacheSessionManager(SessionManager): n_retries = 0 while n_retries < max_retries: session_id = super(MemcacheSessionManager, self).new_session_id(max_retries) - session_key = self.session_key(session_id) - session_data = self.mc.get(session_key) + session_data = self.get_session_data(session_id) if session_data is None: break n_retries += 1 @@ -843,6 +921,21 @@ class MemcacheSessionManager(SessionManager): ''' return 'ipa.session.%s' % (session_id) + def get_session_data(self, session_id): + ''' + Given a session id retrieve the session data associated with it. + If no session data exists for the session id return None. + + :parameters: + session_id + The session id whose session data is desired. + :returns: + Session data if found, None otherwise. + ''' + session_key = self.session_key(session_id) + session_data = self.mc.get(session_key) + return session_data + def get_session_id_from_http_cookie(self, cookie_header): ''' Parse an HTTP cookie header and search for our session @@ -904,8 +997,7 @@ class MemcacheSessionManager(SessionManager): self.store_session_data(session_data) return session_data else: - session_key = self.session_key(session_id) - session_data = self.mc.get(session_key) + session_data = self.get_session_data(session_id) if session_data is None: self.debug('no session data in cache with id=%s, generating empty session data', session_id) session_data = self.new_session_data(session_id) @@ -1094,5 +1186,29 @@ def delete_krbccache_file(krbccache_pathname=None): #------------------------------------------------------------------------------- +from ipalib.request import context + +class session_logout(Command): + ''' + RPC command used to log the current user out of their session. + ''' + + def execute(self, *args, **options): + session_data = getattr(context, 'session_data', None) + if session_data is None: + self.debug('session logout command: no session_data found') + else: + session_id = session_data.get('session_id') + self.debug('session logout command: session_id=%s', session_id) + + # Notifiy registered listeners + session_mgr.auth_mgr.logout(session_data) + + return dict(result=None) + +api.register(session_logout) + +#------------------------------------------------------------------------------- + session_mgr = MemcacheSessionManager() diff --git a/ipaserver/plugins/xmlserver.py b/ipaserver/plugins/xmlserver.py index 03bca9a80..d2a28eca8 100644 --- a/ipaserver/plugins/xmlserver.py +++ b/ipaserver/plugins/xmlserver.py @@ -25,8 +25,9 @@ Loads WSGI server plugins. from ipalib import api if 'in_server' in api.env and api.env.in_server is True: - from ipaserver.rpcserver import session, xmlserver, jsonserver, krblogin - api.register(session) + from ipaserver.rpcserver import wsgi_dispatch, xmlserver, jsonserver_kerb, jsonserver_session, krblogin + api.register(wsgi_dispatch) api.register(xmlserver) - api.register(jsonserver) + api.register(jsonserver_kerb) + api.register(jsonserver_session) api.register(krblogin) diff --git a/ipaserver/rpcserver.py b/ipaserver/rpcserver.py index 205dc7655..d0bb605f5 100644 --- a/ipaserver/rpcserver.py +++ b/ipaserver/rpcserver.py @@ -32,9 +32,9 @@ from ipalib.request import context, Connection, destroy_context from ipalib.rpc import xml_dumps, xml_loads from ipalib.util import make_repr, parse_time_duration from ipapython.compat import json -from ipalib.session import session_mgr, read_krbccache_file, store_krbccache_file, delete_krbccache_file, fmt_time, default_max_session_lifetime +from ipalib.session import session_mgr, AuthManager, read_krbccache_file, store_krbccache_file, delete_krbccache_file, fmt_time, default_max_session_lifetime from ipalib.backend import Backend -from ipalib.krb_utils import krb5_parse_ccache, KRB5_CCache, krb5_format_tgt_principal_name, krb5_format_service_principal_name, krb_ticket_expiration_threshold +from ipalib.krb_utils import krb5_parse_ccache, KRB5_CCache, krb_ticket_expiration_threshold from wsgiref.util import shift_path_info from ipapython.version import VERSION import base64 @@ -118,18 +118,17 @@ def extract_query(environ): return query -class session(Executioner): +class wsgi_dispatch(Executioner): """ WSGI routing middleware and entry point into IPA server. - The `session` plugin is the entry point into the IPA server. It will create - an LDAP connection (from a session cookie or the KRB5CCNAME header) and then - dispatch the request to the appropriate application. In WSGI parlance, - `session` is *middleware*. + The `wsgi_dispatch` plugin is the entry point into the IPA server. + It dispatchs the request to the appropriate wsgi application + handler which is specific to the authentication and RPC mechanism. """ def __init__(self): - super(session, self).__init__() + super(wsgi_dispatch, self).__init__() self.__apps = {} def __iter__(self): @@ -143,7 +142,7 @@ class session(Executioner): return key in self.__apps def __call__(self, environ, start_response): - self.debug('WSGI session.__call__:') + self.debug('WSGI wsgi_dispatch.__call__:') try: return self.route(environ, start_response) finally: @@ -151,10 +150,10 @@ class session(Executioner): def _on_finalize(self): self.url = self.env['mount_ipa'] - super(session, self)._on_finalize() + super(wsgi_dispatch, self)._on_finalize() def route(self, environ, start_response): - key = shift_path_info(environ) + key = environ.get('PATH_INFO') if key in self.__apps: app = self.__apps[key] return app(environ, start_response) @@ -189,8 +188,8 @@ class WSGIExecutioner(Executioner): def set_api(self, api): super(WSGIExecutioner, self).set_api(api) - if 'session' in self.api.Backend: - self.api.Backend.session.mount(self, self.key) + if 'wsgi_dispatch' in self.api.Backend: + self.api.Backend.wsgi_dispatch.mount(self, self.key) def _on_finalize(self): self.url = self.env.mount_ipa + self.key @@ -302,7 +301,7 @@ class xmlserver(WSGIExecutioner): """ content_type = 'text/xml' - key = 'xml' + key = '/xml' def _on_finalize(self): self.__system = { @@ -317,6 +316,10 @@ class xmlserver(WSGIExecutioner): ''' self.debug('WSGI xmlserver.__call__:') + ccache=environ.get('KRB5CCNAME') + if ccache is None: + return self.marshal(None, CCacheError()) + self.create_context(ccache=ccache) try: self.create_context(ccache=environ.get('KRB5CCNAME')) response = super(xmlserver, self).__call__(environ, start_response) @@ -339,23 +342,6 @@ class xmlserver(WSGIExecutioner): def methodHelp(self, *params): return u'methodHelp not implemented' - def marshaled_dispatch(self, data, ccache, client_ip): - """ - Execute the XML-RPC request contained in ``data``. - """ - try: - self.create_context(ccache=ccache, client_ip=client_ip) - (params, name) = xml_loads(data) - if name in self.__system: - response = (self.__system[name](*params),) - else: - (args, options) = params_2_args_options(params) - response = (self.execute(name, *args, **options),) - except PublicError, e: - self.debug('response: %s: %s', e.__class__.__name__, str(e)) - response = Fault(e.errno, e.strerror) - return xml_dumps(response, methodresponse=True) - def unmarshal(self, data): (params, name) = xml_loads(data) (args, options) = params_2_args_options(params) @@ -489,17 +475,6 @@ class jsonserver(WSGIExecutioner): """ content_type = 'application/json' - key = 'json' - - def need_login(self, start_response): - status = '401 Unauthorized' - headers = [] - response = '' - - self.debug('jsonserver: %s', status) - - start_response(status, headers) - return [response] def __call__(self, environ, start_response): ''' @@ -507,51 +482,7 @@ class jsonserver(WSGIExecutioner): self.debug('WSGI jsonserver.__call__:') - # Load the session data - session_data = session_mgr.load_session_data(environ.get('HTTP_COOKIE')) - session_id = session_data['session_id'] - - self.debug('jsonserver.__call__: session_id=%s start_timestamp=%s write_timestamp=%s expiration_timestamp=%s', - session_id, - fmt_time(session_data['session_start_timestamp']), - fmt_time(session_data['session_write_timestamp']), - fmt_time(session_data['session_expiration_timestamp'])) - - ccache_data = session_data.get('ccache_data') - - # Redirect to login if no Kerberos credentials - if ccache_data is None: - self.debug('no ccache, need login') - return self.need_login(start_response) - - krbccache_pathname = store_krbccache_file(ccache_data) - - # Redirect to login if Kerberos credentials are expired - cc = KRB5_CCache(krbccache_pathname) - ldap_principal = krb5_format_service_principal_name('ldap', self.api.env.host, self.api.env.realm) - tgt_principal = krb5_format_tgt_principal_name(self.api.env.realm) - if not (cc.credential_is_valid(ldap_principal) or cc.credential_is_valid(tgt_principal)): - self.debug('ccache expired, deleting session, need login') - session_mgr.delete_session_data(session_id) - delete_krbccache_file(krbccache_pathname) - return self.need_login(start_response) - - # Store the session data in the per-thread context - setattr(context, 'session_data', session_data) - - self.create_context(ccache=krbccache_pathname) - - try: - response = super(jsonserver, self).__call__(environ, start_response) - finally: - # Kerberos may have updated the ccache data, refresh our copy of it - session_data['ccache_data'] = read_krbccache_file(krbccache_pathname) - # Delete the temporary ccache file we used - delete_krbccache_file(krbccache_pathname) - # Store the session data. - session_mgr.store_session_data(session_data) - destroy_context() - + response = super(jsonserver, self).__call__(environ, start_response) return response def marshal(self, result, error, _id=None): @@ -606,15 +537,154 @@ class jsonserver(WSGIExecutioner): options = dict((str(k), v) for (k, v) in options.iteritems()) return (method, args, options, _id) +class AuthManagerKerb(AuthManager): + ''' + Instances of the AuthManger class are used to handle + authentication events delivered by the SessionManager. This class + specifcally handles the management of Kerbeos credentials which + may be stored in the session. + ''' + + def __init__(self, name): + super(AuthManagerKerb, self).__init__(name) + + def logout(self, session_data): + ''' + The current user has requested to be logged out. To accomplish + this we remove the user's kerberos credentials from their + session. This does not destroy the session, it just prevents + it from being used for fast authentication. Because the + credentials are no longer in the session cache any future + attempt will require the acquisition of credentials using one + of the login mechanisms. + ''' + + if session_data.has_key('ccache_data'): + self.debug('AuthManager.logout.%s: deleting ccache_data', self.name) + del session_data['ccache_data'] + else: + self.error('AuthManager.logout.%s: session_data does not contain ccache_data', self.name) + + +class jsonserver_session(jsonserver): + """ + JSON RPC server protected with session auth. + """ + + key = '/session/json' + + def __init__(self): + super(jsonserver_session, self).__init__() + auth_mgr = AuthManagerKerb(self.__class__.__name__) + session_mgr.auth_mgr.register(auth_mgr.name, auth_mgr) + + def need_login(self, start_response): + status = '401 Unauthorized' + headers = [] + response = '' + + self.debug('jsonserver_session: %s', status) + + start_response(status, headers) + return [response] + + def __call__(self, environ, start_response): + ''' + ''' + + self.debug('WSGI jsonserver_session.__call__:') + + # Load the session data + session_data = session_mgr.load_session_data(environ.get('HTTP_COOKIE')) + session_id = session_data['session_id'] + + self.debug('jsonserver_session.__call__: session_id=%s start_timestamp=%s write_timestamp=%s expiration_timestamp=%s', + session_id, + fmt_time(session_data['session_start_timestamp']), + fmt_time(session_data['session_write_timestamp']), + fmt_time(session_data['session_expiration_timestamp'])) + + ccache_data = session_data.get('ccache_data') + + # Redirect to login if no Kerberos credentials + if ccache_data is None: + self.debug('no ccache, need login') + return self.need_login(start_response) + + krbccache_pathname = store_krbccache_file(ccache_data) + + # Redirect to login if Kerberos credentials are expired + cc = KRB5_CCache(krbccache_pathname) + if not cc.valid(self.api.env.host, self.api.env.realm): + self.debug('ccache expired, deleting session, need login') + delete_krbccache_file(krbccache_pathname) + return self.need_login(start_response) + + # Store the session data in the per-thread context + setattr(context, 'session_data', session_data) + + self.create_context(ccache=krbccache_pathname) + + try: + response = super(jsonserver_session, self).__call__(environ, start_response) + finally: + # Kerberos may have updated the ccache data during the + # execution of the command therefore we need refresh our + # copy of it in the session data so the next command sees + # the same state of the ccache. + # + # However we must be careful not to restore the ccache + # data in the session data if it was explicitly deleted + # during the execution of the command. For example the + # logout command removes the ccache data from the session + # data to invalidate the session credentials. + + if session_data.has_key('ccache_data'): + session_data['ccache_data'] = read_krbccache_file(krbccache_pathname) + + # Delete the temporary ccache file we used + delete_krbccache_file(krbccache_pathname) + # Store the session data. + session_mgr.store_session_data(session_data) + destroy_context() + + return response + +class jsonserver_kerb(jsonserver): + """ + JSON RPC server protected with kerberos auth. + """ + + key = '/json' + + def __call__(self, environ, start_response): + ''' + ''' + + self.debug('WSGI jsonserver_kerb.__call__:') + + ccache=environ.get('KRB5CCNAME') + if ccache is None: + return self.marshal(None, CCacheError()) + self.create_context(ccache=ccache) + + try: + response = super(jsonserver_kerb, self).__call__(environ, start_response) + finally: + destroy_context() + + return response + + class krblogin(Backend): - key = 'login' + key = '/login' def __init__(self): super(krblogin, self).__init__() def _on_finalize(self): super(krblogin, self)._on_finalize() - self.api.Backend.session.mount(self, self.key) + self.api.Backend.wsgi_dispatch.mount(self, self.key) # Set the session expiration time try: @@ -652,8 +722,7 @@ class krblogin(Backend): # Compute when the session will expire cc = KRB5_CCache(ccache) - tgt_principal = krb5_format_tgt_principal_name(self.api.env.realm) - authtime, starttime, endtime, renew_till = cc.get_credential_times(tgt_principal) + endtime = cc.endtime(self.api.env.host, self.api.env.realm) # Account for clock skew and/or give us some time leeway krb_expiration = endtime - krb_ticket_expiration_threshold @@ -673,7 +742,7 @@ class krblogin(Backend): status = '200 Success' response = '' - session_cookie = session_mgr.generate_cookie('/ipa', session_data['session_id']) + session_cookie = session_mgr.generate_cookie('/ipa', session_id) headers.append(('Set-Cookie', session_cookie)) start_response(status, headers) diff --git a/lite-server.py b/lite-server.py index b7067a56c..e06535784 100755 --- a/lite-server.py +++ b/lite-server.py @@ -124,7 +124,7 @@ if __name__ == '__main__': urlmap = URLMap() apps = [ - ('IPA', KRBCheater(api.Backend.session)), + ('IPA', KRBCheater(api.Backend.wsgi_dispatch)), ('webUI', KRBCheater(WebUIApp())), ] for (name, app) in apps: @@ -68,6 +68,8 @@ class IPATypeChecker(TypeChecker): 'ipalib.parameters.File': ['stdin_if_missing'], 'urlparse.SplitResult': ['netloc'], 'ipalib.krb_utils.KRB5_CCache' : ['log', 'debug', 'info', 'warning', 'error', 'critical', 'exception'], + 'ipalib.session.AuthManager' : ['log', 'debug', 'info', 'warning', 'error', 'critical', 'exception'], + 'ipalib.session.SessionAuthManager' : ['log', 'debug', 'info', 'warning', 'error', 'critical', 'exception'], 'ipalib.session.SessionManager' : ['log', 'debug', 'info', 'warning', 'error', 'critical', 'exception'], 'ipalib.session.SessionCCache' : ['log', 'debug', 'info', 'warning', 'error', 'critical', 'exception'], 'ipalib.session.MemcacheSessionManager' : ['log', 'debug', 'info', 'warning', 'error', 'critical', 'exception'], diff --git a/tests/test_ipaserver/test_rpcserver.py b/tests/test_ipaserver/test_rpcserver.py index 9aa16d0ce..e712078d7 100644 --- a/tests/test_ipaserver/test_rpcserver.py +++ b/tests/test_ipaserver/test_rpcserver.py @@ -84,7 +84,7 @@ def test_params_2_args_options(): class test_session(object): - klass = rpcserver.session + klass = rpcserver.wsgi_dispatch def test_route(self): def app1(environ, start_response): @@ -125,7 +125,7 @@ class test_session(object): # Test that StandardError is raise if trying override a mount: e = raises(StandardError, inst.mount, app2, 'foo') assert str(e) == '%s.mount(): cannot replace %r with %r at %r' % ( - 'session', app1, app2, 'foo' + 'wsgi_dispatch', app1, app2, 'foo' ) # Test mounting a second app: @@ -141,7 +141,7 @@ class test_xmlserver(PluginTester): _plugin = rpcserver.xmlserver - def test_marshaled_dispatch(self): + def test_marshaled_dispatch(self): # FIXME (o, api, home) = self.instance('Backend', in_server=True) |