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

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

Added a Policy Information Point to encapsulate subject attribute retrieval.

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