source: TI12-security/trunk/python/ndg.security.common/ndg/security/common/SessionMgr/__init__.py @ 1783

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI12-security/trunk/python/ndg.security.common/ndg/security/common/SessionMgr/__init__.py@1783
Revision 1783, 19.6 KB checked in by pjkersha, 15 years ago (diff)

All Session Manager Client unit tests working with Session Manager service stub over https:

server/SessionMgr/server-config.tac
server/SessionMgr/SessionMgr_services_server.py
common/SessionMgr/SessionMgr_services.py
common/SessionMgr/SessionMgr_services_types.py
common/SessionMgr/init.py - added disconnect method to SessionMgrClient? class.

common/XMLSecDoc.py: comment out xmlsec for the moment. This module will need to be refactored
to use new digital signature code as used in WS-Security code tests.

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