source: TI12-security/trunk/python/ndg.security.server/ndg/security/server/wsgi/utils/sessionmanagerclient.py @ 4584

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI12-security/trunk/python/ndg.security.server/ndg/security/server/wsgi/utils/sessionmanagerclient.py@4584
Revision 4584, 11.2 KB checked in by pjkersha, 12 years ago (diff)

Started integration work for common WSGI/SOAP client based interfaces (ndg.security.server.wsgi.utils.sessionmanagerclient and ndg.security.server.wsgi.utils.attributeauthorityclient) with Pylons Single Sign On package (ndg.security.server.sso)

Line 
1"""NDG Security
2
3Client interface to Session Manager for WSGI based applications
4
5NERC Data Grid Project
6
7This software may be distributed under the terms of the Q Public License,
8version 1.0 or later.
9"""
10__author__ = "P J Kershaw"
11__date__ = "27/11/08"
12__copyright__ = "(C) 2008 STFC & NERC"
13__contact__ = "Philip.Kershaw@stfc.ac.uk"
14__revision__ = "$Id$"
15
16import logging
17log = logging.getLogger(__name__)
18
19import sys
20import os
21
22from ndg.security.server.wsgi.utils.attributeauthorityclient import \
23    WSGIAttributeAuthorityClient
24
25# Session Manager Authentication interface ...
26from ndg.security.server.sessionmanager import AuthNServiceError, \
27    AuthNServiceInvalidCredentials, AuthNServiceRetrieveError, \
28    AuthNServiceInitError, AuthNServiceConfigError
29
30# Session Manager SOAP client interface
31from ndg.security.common.sessionmanager import SessionManagerClient
32   
33# Import exception types from Session Manager and Session Manager client to
34# give caller some capability to trap errors
35# Session Manager server side exceptions ...
36from ndg.security.server.sessionmanager import SessionManagerError, \
37    UserSessionExpired, UserSessionX509CertNotBeforeTimeError, \
38    InvalidUserSession, CredentialWalletAttributeRequestDenied
39   
40from ndg.security.server.sessionmanager import SessionNotFound as \
41    _SrvSessionNotFound
42
43# ... and client side exceptions ...
44from ndg.security.common.sessionmanager import SessionNotFound as \
45    _ClntSessionNotFound
46
47from ndg.security.common.sessionmanager import SessionExpired as \
48    _ClntSessionExpired
49
50from ndg.security.common.sessionmanager import InvalidSession as \
51    _ClntInvalidSession
52 
53from ndg.security.common.sessionmanager import AttributeRequestDenied as \
54    _ClntAttributeRequestDenied
55     
56from ndg.security.common.sessionmanager import InvalidSessionManagerClientCtx,\
57    SessionManagerClientError, SessionCertTimeError
58
59# Combine Session not found exception classes as raised from server and
60# client side to enable convenient exception handling by a client to this
61# class.  e.g. a call to WSGISessionManager.connect without the need to know
62# whether the wrapper is calling a remote service over the SOAP interface or
63# the service locally via a reference a Session Manager in environ:
64#
65# try:
66#     wsgiClnt.connect(username, passphrase=p)
67# except SessionNotFound, e:
68#     #  do something
69#     raise
70#     
71# Rather than having to do:
72#
73# try:
74#     wsgiClnt.connect(username, passphrase=p)
75# except (ndg.security.server.sessionmanager.SessionNotFound,
76#         ndg.security.common.sessionmanager.SessionNotFound), e:
77#     #  do something
78#     raise
79SessionNotFound = (_SrvSessionNotFound, _ClntSessionNotFound)
80
81# Combine client and server session not before time error exceptions to
82# enable easier exception handling for a WSGISessionManagerClient caller. 
83# See SessionNotFound.__doc__ for more details of reasoning
84SessionNotBeforeTimeError = (UserSessionX509CertNotBeforeTimeError, 
85                             SessionCertTimeError)
86
87# Combine client and server session expired exceptions to enable easier
88# exception handling for a WSGISessionManagerClient caller.  See
89# SessionNotFound.__doc__ for more details of reasoning
90SessionExpired = (UserSessionExpired, _ClntSessionExpired)
91
92# Combine client and server invalid session exceptions to enable easier
93# exception handling for a WSGISessionManagerClient caller.  See
94# SessionNotFound.__doc__ for more details of reasoning"""
95InvalidSession = (InvalidUserSession, _ClntInvalidSession)
96   
97# Combine client and server invalid session exceptions to enable easier
98# exception handling for a WSGISessionManagerClient caller.  See
99# SessionNotFound.__doc__ for more details of reasoning
100AttributeRequestDenied = (CredentialWalletAttributeRequestDenied, 
101                          _ClntAttributeRequestDenied)
102
103# End of server/client side exception combinations
104
105       
106class WSGISessionManagerClientError(Exception):
107    """Base class exception for WSGI Session Manager client errors"""
108   
109class WSGISessionManagerClientConfigError(WSGISessionManagerClientError):
110    """Configuration error for WSGI Session Manager Client"""
111   
112class WSGISessionManagerClient(object):
113    """Client interface to Session Manager for WSGI based applications
114   
115    This class wraps the SOAP based web service client and alternate access to
116    a Session Manager instance in the same code stack available via an environ
117    keyword
118    """
119    environKey = "ndg.security.server.wsgi.sessionManagerFilter"
120
121    _refInEnviron = lambda self: self._environKey in self._environ
122   
123    # Define as property for convenient call syntax
124    refInEnviron = property(fget=_refInEnviron,
125                            doc="return True if a Session Manager instance is "
126                                "available in WSGI environ")
127   
128    _getRef = lambda self:self._environ[self._environKey].serviceSOAPBinding.sm
129    ref = property(fget=_getRef, doc="Session Manager local instance")
130
131   
132    def __init__(self, environKey=None, environ={}, **soapClientKw):
133 
134        log.debug("WSGISessionManagerClient.__init__ ...")
135       
136        self._environKey = environKey or WSGISessionManagerClient.environKey
137       
138        # Standard WSGI environment dict
139        self._environ = environ
140       
141        if 'uri' in soapClientKw:
142            self._soapClient = SessionManagerClient(**soapClientKw)
143        else:
144            self._soapClient = None
145   
146    def _setEnviron(self, environ):
147        if not isinstance(environ, dict):
148            raise TypeError("Expecting dict type for 'environ' property")
149        self._environ = environ
150       
151    def _getEnviron(self, environ):
152        return self._environ
153   
154    environ = property(fget=_getEnviron, 
155                       fset=_setEnviron, 
156                       doc="WSGI environ dictionary")
157   
158    def connect(self, username, **kw):
159        """Request a new user session from the Session Manager
160       
161        @type username: string
162        @param username: the username of the user to connect
163        """
164   
165        if self.refInEnviron:
166            log.debug("Connecting to local Session Manager instance")
167            if 'username' in kw:
168                raise TypeError("connect() got an unexpected keyword argument "
169                                "'username'")
170               
171            # Connect to local instance
172            res = self.ref.connect(username=username, **kw)
173        else:
174            log.debug("Connecting to remote Session Manager service")
175           
176            # Filter out keywords which apply to a Session Manager local
177            # instance call
178            kw.pop('userX509Cert', None)
179           
180            # Make connection to remote service
181            res = self._soapClient.connect(username, **kw)
182   
183            # Convert from unicode because unicode causes problems with
184            # M2Crypto private key load
185            res = tuple([isinstance(i,unicode) and str(i) or i for i in res])
186           
187        return res
188   
189   
190    def disconnect(self, **kw):
191        """Delete an existing user session from the Session Manager
192       
193        @type **kw: dict
194        @param **kw: disconnect keywords applicable to
195        ndg.security.server.sessionmanager.SessionManager.getSessionStatus and
196        ndg.security.common.sessionmanager.SessionManagerClient.getSessionStatus
197        the SOAP client"""
198   
199        # Modify keywords according to correct interface for server side /
200        # SOAP client
201        if self.refInEnviron:
202            if 'userDN' in kw:
203                log.warning('Removing keyword "userDN": this is not supported '
204                            'for calls to ndg.security.server.sessionmanager.'
205                            'SessionManager.deleteUserSession')
206                kw.pop('userX509Cert', None)
207               
208            self.ref.deleteUserSession(**kw)
209        else:
210            if 'userX509Cert' in kw:
211                kw['userDN'] = kw.pop('userX509Cert').dn
212               
213            self._soapClient.disconnect(**kw)
214       
215   
216    def getSessionStatus(self, **kw):
217        """Check for the existence of a session with a given
218        session ID / user certificate Distinguished Name
219                               
220        @type **kw: dict
221        @param **kw: disconnect keywords applicable to
222        ndg.security.server.sessionmanager.SessionManager.getSessionStatus and
223        ndg.security.common.sessionmanager.SessionManagerClient.getSessionStatus
224        the SOAP client"""
225   
226        if self.refInEnviron:
227            return self.ref.getSessionStatus(**kw)
228        else:
229            return self._soapClient.getSessionStatus(**kw)
230   
231
232
233    def getAttCert(self, **kw):
234        """Request NDG Session Manager to retrieve an Attribute
235        Certificate from the given Attribute Authority and cache it in the
236        user's credential wallet held by the session manager.
237       
238        @type **kw: dict
239        @param **kw: disconnect keywords applicable to
240        ndg.security.server.sessionmanager.SessionManager.getAttCert and
241        ndg.security.common.sessionmanager.SessionManagerClient.getAttCert
242        the SOAP client
243        """
244       
245        if self.refInEnviron:
246            # Connect to local instance
247            if kw.get('attributeAuthorityURI') is None and \
248               kw.get('attributeAuthority') is None:
249                wsgiAttributeAuthorityClient = WSGIAttributeAuthorityClient(
250                                                        environ=self._environ)
251
252                if wsgiAttributeAuthorityClient.refInEnviron:
253                    kw['attributeAuthority'] = wsgiAttributeAuthorityClient.ref
254                else:
255                    raise WSGISessionManagerClientConfigError(
256                        "No Attribute Authority URI or server object has been "
257                        "set and no reference is available in environ")
258                   
259            return self.ref.getAttCert(**kw)
260        else:
261            # Filter out keywords which apply to a Session Manager local
262            # instance call
263            if 'username' in kw:
264                kw.pop('username')
265                log.warning('Trying call via SOAP interface: '
266                            'removing the "username" keyword '
267                            'ndg.security.common.sessionmanager.'
268                            'SessionManagerClient.getAttCert doesn\'t support '
269                            'this keyword')
270               
271            if 'refreshAttCert' in kw:
272                kw.pop('refreshAttCert')
273                log.warning('Trying call via SOAP interface: '
274                            'removing the "refreshAttCert" keyword '
275                            'ndg.security.common.sessionmanager.'
276                            'SessionManagerClient.getAttCert doesn\'t support '
277                            'this keyword')
278               
279            if 'attCertRefreshElapse' in kw:
280                kw.pop('attCertRefreshElapse')
281                log.warning('Trying call via SOAP interface: '
282                            'removing the "attCertRefreshElapse" keyword '
283                            'ndg.security.common.sessionmanager.'
284                            'SessionManagerClient.getAttCert doesn\'t support '
285                            'this keyword')
286
287            return self._soapClient.getAttCert(**kw)
Note: See TracBrowser for help on using the repository browser.