source: TI12-security/trunk/python/NDG/SessionClient.py @ 784

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI12-security/trunk/python/NDG/SessionClient.py@784
Revision 784, 18.7 KB checked in by pjkersha, 14 years ago (diff)

Fixes for CEH and PML installations...

conf/sessionMgrProperties.xml: added missing <simpleCASrvProp> tag.
NDG/SimpleCA.py: fixed bug in setProperties method - lTime var was ref'd but not set.
NDG/SessionClient.py: addUser method - move if 'errMsg' ... block out of exception handling
block for greater efficiency.
NDG/Session.py: addUser method of SessionMgr? class - fixed bug return AddUserResp? instance
instead of trying to raise an exception with it.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1#!/usr/bin/env python
2
3"""NDG Session client - makes requests for authentication and authorisation
4
5NERC Data Grid Project
6
7P J Kershaw 16/08/05
8
9Copyright (C) 2005 CCLRC & NERC
10
11This software may be distributed under the terms of the Q Public License,
12version 1.0 or later.
13"""
14
15cvsID = '$Id$'
16
17from ZSI import ServiceProxy
18import sys
19import os
20from Cookie import SimpleCookie
21
22from X509 import *
23from SessionMgrIO import *
24
25# Handle retrieval of public key cert for Session Manager at remote location
26import tempfile
27import urllib
28
29#_____________________________________________________________________________
30class SessionClientError(Exception):
31    """Exception handling for SessionClient class"""
32    def __init__(self, msg):
33        self.__msg = msg
34         
35    def __str__(self):
36        return self.__msg
37
38
39#_____________________________________________________________________________       
40class SessionClient(object):
41    """Client interface to Session Manager Web Service"""
42   
43    #_________________________________________________________________________
44    def __init__(self, 
45                 smWSDL=None, 
46                 smPubKeyFilePath=None,
47                 clntPubKeyFilePath=None,
48                 clntPriKeyFilePath=None,
49                 traceFile=None):
50        """
51        smWSDL:                  WSDL URI for Session Manager WS.  Setting it
52                                 will set the Service Proxy
53        smPubKeyFilePath:   
54                                 Public key of Session Manager used to encrypt
55                                 the outgoing message if required - set as a
56                                 path on the local file system or as a URI
57        clntPubKeyFilePath:      Public key of client.  This is passed to the
58                                 Session Manager so that it can encrypt
59                                 responses.  WARNING: if not set, responses
60                                 are returned as clear text
61        clntPriKeyFilePath:      Private key of client.  If clntPubKeyFilePath
62                                 is set, the private key is needed to decrypt
63                                 the response from the Session Manager
64        traceFile:               set to file object such as sys.stderr to
65                                 give extra WS debug information"""
66
67        self.__smSrv = None
68        self.__smWSDL = None
69        self.__smPubKeyFilePath = None
70        self.__smPubKeyFilePath = None
71        self.__clntPubKeyFilePath = None
72        self.__clntPubKey = None
73        self.__clntPriKeyFilePath = None
74       
75        self.__smPubKeyTempFile = None
76       
77       
78        if smWSDL:
79            self.__setSMwsdl(smWSDL)
80           
81        if smPubKeyFilePath:
82            self.__setSMpubKeyFilePath(smPubKeyFilePath)
83           
84        if clntPriKeyFilePath:
85            self.__setClntPriKeyFilePath(clntPriKeyFilePath)
86           
87        if clntPubKeyFilePath:
88            if clntPriKeyFilePath is None:
89                raise SessionClientError(\
90                    "A Client private key file is required as well a " + \
91                    "public key")
92                   
93            self.__setClntPubKeyFilePath(clntPubKeyFilePath)
94
95           
96        self.__traceFile = traceFile
97
98         
99        # Instantiate Session Manager WS proxy
100        if self.__smWSDL:
101            self.serviceProxy()
102       
103
104    #_________________________________________________________________________
105    def __setSMwsdl(self, smWSDL):
106       
107        if not isinstance(smWSDL, basestring):
108            raise SessionClientError(\
109                            "Session Manager WSDL URI must be a valid string")
110       
111        self.__smWSDL = smWSDL
112       
113    smWSDL = property(fset=__setSMwsdl, doc="Set Session Manager WSDL URI")
114
115
116    #_________________________________________________________________________
117    def __setSMpubKeyFilePath(self, smPubKeyFilePath):
118       
119        if not isinstance(smPubKeyFilePath, basestring):
120            raise SessionClientError(\
121                "Session Manager public key URI must be a valid string")
122       
123        self.__smPubKeyFilePath = smPubKeyFilePath
124       
125    smPubKeyFilePath = property(fset=__setSMpubKeyFilePath,
126                           doc="Set Session Manager public key URI")
127
128 
129    #_________________________________________________________________________
130    def __setClntPubKeyFilePath(self, clntPubKeyFilePath):
131       
132        if not isinstance(clntPubKeyFilePath, basestring):
133            raise SessionClientError(\
134                "Client public key file path must be a valid string")
135       
136        self.__clntPubKeyFilePath = clntPubKeyFilePath
137        try:
138            self.__clntPubKey = open(self.__clntPubKeyFilePath).read()
139           
140        except IOError, (errNo, errMsg):
141            raise SessionClientError(\
142                    "Reading certificate file \"%s\": %s" % \
143                    (self.__clntPubKeyFilePath, errMsg))
144                               
145        except Exception, e:
146            raise SessionClientError(\
147                    "Reading certificate file \"%s\": %s" % \
148                    (self.__clntPubKeyFilePath, str(e)))
149       
150    clntPubKeyFilePath = property(fset=__setClntPubKeyFilePath,
151                                  doc="File path for client public key")
152
153 
154    #_________________________________________________________________________
155    def __setClntPriKeyFilePath(self, clntPriKeyFilePath):
156       
157        if not isinstance(clntPriKeyFilePath, basestring):
158            raise SessionClientError(\
159                "Client public key file path must be a valid string")
160       
161        self.__clntPriKeyFilePath = clntPriKeyFilePath
162       
163    clntPriKeyFilePath = property(fset=__setClntPriKeyFilePath,
164                                  doc="File path for client private key")
165
166
167    #_________________________________________________________________________
168    def __getSessionMgrPubKey(self):
169        """Retrieve the public key from the URI"""
170       
171        # Don't proceed unless URI was set - user may have set public key via
172        # smPubKeyFilePath instead
173        if self.__smPubKeyFilePath is not None:
174            return
175               
176        try:
177            self.__smPubKeyTempFile = tempfile.NamedTemporaryFile()
178           
179            pubKey = self.getPubKey()
180            open(self.__smPubKeyTempFile.name, "w").write(pubKey)
181           
182            self.__smPubKeyFilePath = self.__smPubKeyTempFile.name
183           
184        except IOError, (errNo, errMsg):
185            raise SessionClientError(\
186                                "Writing public key to temp \"%s\": %s" % \
187                                (self.__smPubKeyTempFile.name, errMsg))                                                                     
188        except Exception, e:
189            raise SessionClientError("Retrieving Session Manager " + \
190                                     "public key: %s" % str(e))
191   
192       
193    #_________________________________________________________________________
194    def serviceProxy(self, smWSDL=None):
195        """Set the WS proxy for the Session Manager"""
196        if smWSDL:
197            self.__setSMwsdl(smWSDL)
198
199        try:
200            self.__smSrv = ServiceProxy(self.__smWSDL, 
201                                        use_wsdl=True, 
202                                        tracefile=self.__traceFile)
203        except Exception, e:
204            raise SessionClientError("Initialising WSDL Service Proxy: " + \
205                                     str(e))
206
207                                   
208    #_________________________________________________________________________
209    def addUser(self,
210                userName,
211                pPhrase=None,
212                pPhraseFilePath=None,
213                clntPriKeyPwd=None):
214        """Register a new user
215       
216        userName:                the username for the new user
217        pPhrase:                 user's pass-phrase
218        pPhraseFilePath:         a file containing the user's pass-phrase. 
219                                 Use this as an alternative to pPhrase keyword
220        clntPriKeyPwd:           pass-phrase if any for the client's private
221                                 key used to decrypt response from
222                                 Session Manager
223        """
224   
225        if pPhrase is None:
226            try:
227                pPhrase = open(pPhraseFilePath).read().strip()
228           
229            except Exception, e:
230                raise SessionClientError("Pass-phrase not defined: " + str(e))
231
232
233        # If Public key was not set, retrieve from server
234        self.__getSessionMgrPubKey()
235           
236   
237        # Make request for new user
238        try:   
239            addUserReq = AddUserReq(userName=userName, 
240                                pPhrase=pPhrase,
241                                encrCert=self.__clntPubKey,
242                                encrPubKeyFilePath=self.__smPubKeyFilePath) 
243
244            # Pass encrypted request
245            resp = self.__smSrv.addUser(addUserReq=addUserReq())
246                       
247            addUserResp = AddUserResp(xmlTxt=resp['addUserResp'],
248                                encrPriKeyFilePath=self.__clntPriKeyFilePath,
249                                encrPriKeyPwd=clntPriKeyPwd)           
250        except Exception, e:
251            raise SessionClientError("Error adding new user: " + str(e))
252 
253                           
254        if 'errMsg' in addUserResp and addUserResp['errMsg']:
255            raise SessionClientError(addUserResp['errMsg'])
256   
257       
258    #_________________________________________________________________________   
259    def connect(self,
260                userName,
261                pPhrase=None,
262                pPhraseFilePath=None,
263                getCookie=True,
264                createServerSess=False,
265                clntPriKeyPwd=None):
266        """Request a new user session from the Session Manager
267       
268        userName:                the username of the user to connect
269        pPhrase:                 user's pass-phrase
270        pPhraseFilePath:         a file containing the user's pass-phrase. 
271                                 Use this as an alternative to pPhrase
272                                 keyword.
273                                 
274        getCookie:               If set to true, return a cookie to be set in
275                                 a web browser client.  Otherwise, return a
276                                 proxy certificate.
277                                 
278        createServerSess:        If set to True, the SessionMgr will create
279                                 and manage a session for the user but note,
280                                 this flag is ignored and set to True if
281                                 getCookie is set. 
282                                 
283                                 For command line case, where getCookie is
284                                 False, it's possible to choose to have a
285                                 client or server side session using this
286                                 keyword.
287        clntPriKeyPwd:           pass-phrase if any for the client's private
288                                 key used to decrypt response from
289                                 Session Manager."""
290   
291        if pPhrase is None:
292            try:
293                pPhrase = open(pPhraseFilePath).read().strip()
294           
295            except Exception, e:
296                raise SessionClientError("Pass-phrase not defined: " + str(e))
297
298
299        # If Public key was not set, retrieve from server
300        self.__getSessionMgrPubKey()
301
302       
303        # Make connection
304        try: 
305            connectReq = ConnectReq(userName=userName, 
306                                pPhrase=pPhrase,
307                                getCookie=getCookie,
308                                createServerSess=createServerSess,
309                                encrCert=self.__clntPubKey,
310                                encrPubKeyFilePath=self.__smPubKeyFilePath) 
311   
312            # Pass encrypted request
313            resp = self.__smSrv.connect(connectReq=connectReq())
314           
315            connectResp = ConnectResp(xmlTxt=resp['connectResp'],
316                                encrPriKeyFilePath=self.__clntPriKeyFilePath,
317                                encrPriKeyPwd=clntPriKeyPwd)
318                           
319            if 'errMsg' in connectResp and connectResp['errMsg']:
320                raise Exception(connectResp['errMsg'])
321           
322            if 'sessCookie' in connectResp:
323                return connectResp['sessCookie']
324           
325            elif 'proxyCert' in connectResp:
326                return connectResp['proxyCert']
327           
328            else:
329               raise SessionClientError(\
330               "Neither \"sessCookie\" or \"proxyCert\" found in response")
331               
332        except Exception, e:
333            raise SessionClientError(\
334                            "Error connecting to Session Manager: " + str(e))
335   
336   
337    #_________________________________________________________________________
338    def reqAuthorisation(self,
339                         proxyCert=None,
340                         sessCookie=None,
341                         sessID=None,
342                         encrSessMgrWSDLuri=None,
343                         aaWSDL=None,
344                         aaPubKey=None,
345                         reqRole=None,
346                         mapFromTrustedHosts=None,
347                         rtnExtAttCertList=None,
348                         extAttCertList=None,
349                         extTrustedHostList=None,
350                         clntPriKeyPwd=None):   
351        """Request authorisation from NDG Session Manager Web Service.
352       
353        reqAuthorisation([sessCookie=s]|[sessID=i, encrSessMgrWSDLuri=e]|
354                         [proxyCert=p][key=arg, ...])
355        proxyCert:             proxy certificate - use as ID instead of
356                               a cookie in the case of a command line client.
357        sessCookie:            session cookie returned from call to connect()
358                               for a browser client.  Input as a string or
359                               SimpleCookie type.
360        sessID:                session ID.  Input this as well as
361                               encrSessMgrWSDLuri as an alternative to
362                               sessCookie in the case of a browser client.
363        encrSessMgrWSDLuri:    encrypted Session Manager WSDL URI.
364        aaWSDL:                WSDL URI for Attribute Authority WS.
365        aaPubKey:              The Session Manager uses the Public key of the
366                               Attribute Authority to encrypt requests to it.
367        reqRole:               The required role for access to a data set.
368                               This can be left out in which case the
369                               Attribute Authority just returns whatever
370                               Attribute Certificate it has for the user
371        mapFromTrustedHosts:   Allow a mapped Attribute Certificate to be
372                               created from a user certificate from another
373                               trusted host.
374        rtnExtAttCertList:     Set this flag True so that if authorisation is
375                               denied, a list of potential attribute
376                               certificates for mapping may be returned.
377        extAttCertList:        A list of Attribute Certificates from other
378                               trusted hosts from which the target Attribute
379                               Authority can make a mapped certificate
380        extTrustedHostList:    A list of trusted hosts that can be used to
381                               get Attribute Certificates for making a mapped
382                               AC.
383        clntPriKeyPwd:         pass-phrase if any for the client's private
384                               key used to decrypt response from
385                               Session Manager.
386        """
387       
388        if sessCookie:
389            if isinstance(sessCookie, basestring):
390                try:
391                    sessCookie = SimpleCookie(sessCookie)
392                except Exception, e:
393                    raise SessionClientError(\
394                                    "Error parsing session cookie: " + str(e))
395
396            sessID = sessCookie['NDG-ID1'].value
397            encrSessMgrWSDLuri = sessCookie['NDG-ID2'].value
398           
399        elif not sessID and not encrSessMgrWSDLuri and not proxyCert:
400            raise SessionClientError(\
401                '"proxyCert" or "sessCookie or "sessID" and ' + \
402                '"encrSessMgrWSDLuri" keywords must be set')
403
404
405        # If Public key was not set, retrieve from server
406        self.__getSessionMgrPubKey()
407
408           
409        # Make authorisation request
410        try:
411            authReq = AuthorisationReq(aaWSDL=aaWSDL,
412                                 aaPubKey=aaPubKey,
413                                 sessID=sessID, 
414                                 encrSessMgrWSDLuri=encrSessMgrWSDLuri,
415                                 proxyCert=proxyCert,
416                                 reqRole=reqRole,
417                                 mapFromTrustedHosts=mapFromTrustedHosts,
418                                 rtnExtAttCertList=rtnExtAttCertList,
419                                 extAttCertList=extAttCertList,
420                                 extTrustedHostList=extTrustedHostList,
421                                 encrCert=self.__clntPubKey,
422                                 encrPubKeyFilePath=self.__smPubKeyFilePath) 
423                                           
424            resp = self.__smSrv.reqAuthorisation(authorisationReq=authReq())
425            authResp = AuthorisationResp(xmlTxt=resp['authorisationResp'],
426                                encrPriKeyFilePath=self.__clntPriKeyFilePath,
427                                encrPriKeyPwd=clntPriKeyPwd)
428            return authResp
429           
430        except Exception, e:
431            raise SessionClientError(\
432                                "Error in authorisation request: " + str(e))
433
434                                   
435    #_________________________________________________________________________
436    def getPubKey(self):
437        """Retrieve the public key of the Session Manager"""
438       
439        try:   
440            pubKeyReq = PubKeyReq() 
441
442            # Pass request
443            resp = self.__smSrv.getPubKey(pubKeyReq=pubKeyReq())
444                       
445            pubKeyResp = PubKeyResp(xmlTxt=resp['pubKeyResp'])
446                           
447            if 'errMsg' in pubKeyResp and pubKeyResp['errMsg']:
448                raise SessionClientError(pubKeyResp['errMsg'])
449           
450            return pubKeyResp['pubKey']
451       
452        except Exception, e:
453            raise SessionClientError("Error retrieving public key: " + str(e))
454                               
Note: See TracBrowser for help on using the repository browser.