source: TI12-security/trunk/python/NDG/SessionMgrIO.py @ 737

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

ndgSetup.sh: fixed slight typo.

mapConfig.xml: added pubKey tag to allow client to Attribute Authority to use it to encrypt
outbound messages to it.

ndgSessionClient.py:

  • include code to set public key of Attribute Authority so that Session Manager can encrypt

messages to it.

  • -r/--req-autho option now requires the AA WSDL URI. -a is now used to set the AA pub key
  • see previous point.

AttAuthorityIO.py:

  • Changed tag 'clntCert' to 'encrCert' so as to be consistent with SessionMgrIO.py code.

attAuthority_services_server.py:

  • Moved encrypt/decrypt code here from AttAuthority? class to be consistent with

sessionMgr_services_server.py.

AttAuthority?.py:

  • Now inherits from dict to allow convenient access to properties file parameters as dictionary

items.

  • Added code to include pubKey tag from mapConfig file in trustedHostInfo returned from

getTrustedHostInfo.

SessionMgrIO.py:

output XML.

  • Shifted test code into separate file in Tests/

SessionClient?.py:

  • Added aaPubKey to reqAuthorisation method - see above re. passing AA public key for

encryption of messages.

sessionMgr_services_server.py:

  • Changes to comments.

Session.py:

private key info of client to allow encrypt of responses from other WSs that SessionMgr? calls.
These are actually passed into CredWallet? instance of UserSession?.

  • AA Public key is passed into reqAuthorisation. This is written to a temp file for use by

XMLSec encryption code.

CredWallet?.py:

  • CredWalletAuthorisationDenied? - make sure extAttCertList gets set to []
  • Added pub/private functionality for encryption of messages to and from Attribute Authorities.
  • reqAuthorisation and getAATrustedHostInfo methods - read in client public key using

straight open/read: using X509Cert.asString() misses out the actual MIME encoded cert text(!)

  • Changed reqAuthorisation() - a required role is now optional with mapFromTrustedHosts flag set.

It does help though with finding a suitable AttCert? for mapping.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1"""NDG Session Manager Web Services helper classes for I/O between client
2and server
3
4NERC Data Grid Project
5
6P J Kershaw 14/12/05
7
8Copyright (C) 2005 CCLRC & NERC
9
10This software may be distributed under the terms of the Q Public License,
11version 1.0 or later.
12"""
13
14cvsID = '$Id$'
15
16# For new line symbol
17import os
18
19# Use _getframe to allow setting of attributes by derived class methods
20import sys
21
22# Filter out xml headers from returned attribute certificates in
23# AuthorisationResp
24import re
25
26from XMLMsg import *
27
28# For use with AuthorisationResp class
29from AttCert import *
30 
31
32#_____________________________________________________________________________
33class ConnectReqError(XMLMsgError):   
34    """Exception handling for NDG SessionMgr WS connect request class."""
35    pass
36
37
38#_____________________________________________________________________________
39class ConnectReq(XMLMsg):
40    """For client to Session Manager WS connect(): formats inputs for request
41    into XML and encrypts.
42   
43    For Session Manager enables decryption of result"""
44   
45    # Override base class class variables
46    xmlTagTmpl = {  "userName":          "",
47                    "pPhrase":           "",
48                    "proxyCert":         "",
49                    "sessID":            "",
50                    "getCookie":         "",
51                    "createServerSess":  "",
52                    "encrCert":          ""    }
53                       
54
55    def __init__(self, **xmlMsgKeys):
56        """XML for sending encrypted credentials to Session Manager connect
57       
58        xmlMsgKeys:    keywords for XMLMsg super-class.  If XML tags are
59                       input as keywords then 'userName' and 'pPhrase' or
60                       'proxyCert' or 'sessID' must be input as the bare
61                       minimum required for SessionMgr connect request.
62        """
63       
64                               
65        # Check for encrypted text or valid credentials
66        if 'encrXMLtxt' not in xmlMsgKeys and 'xmlTxt' not in xmlMsgKeys:           
67
68            # XML tags input as keywords expected - check minimum
69            # required are present for SessionMgr connect request
70            if 'userName' not in xmlMsgKeys and 'pPhrase' not in xmlMsgKeys:
71                if 'proxyCert' not in xmlMsgKeys:
72                    if 'sessID' not in xmlMsgKeys:
73                        raise ConnectReqError(\
74                            "Credentials must be: \"userName\" and " + \
75                            "\"pPhrase\" or \"proxyCert\" or \"sessID\"")
76               
77        # Allow user credentials to be access like dictionary keys
78        super(self.__class__, self).__init__(**xmlMsgKeys)
79
80
81    #_________________________________________________________________________
82    def parseXML(self):
83        """Override base class implementation to include extra code
84        to parse extAttCertList tag"""
85       
86        rootElem = super(self.__class__, self).parseXML(rtnRootElem=True)
87        self['getCookie'] = bool(int(self['getCookie']))
88
89
90#_____________________________________________________________________________
91class ConnectRespError(XMLMsgError):   
92    """Exception handling for NDG SessionMgr WS connect response class."""
93    pass
94
95
96#_____________________________________________________________________________
97class ConnectResp(XMLMsg):
98    """For client to Session Manager WS connect(): formats connect response
99    from SessionMgr.
100   
101    For client, enables decryption of response"""
102   
103    # Override base class class variables
104    xmlTagTmpl = {  "proxyCert":   "",
105                    "sessCookie":  "",
106                    "errMsg":      ""    }
107                       
108
109    def __init__(self, **xmlMsgKeys):
110        """XML for receiving credentials from Session Manager connect call
111       
112        xmlMsgKeys:    keywords for XMLMsg super-class.  If XML tags are
113                       input as keywords then 'proxyCert' or 'sessCookie'
114                       must be set.                       
115        """       
116       
117        # Allow user credentials to be access like dictionary keys
118        super(self.__class__, self).__init__(**xmlMsgKeys)
119       
120                               
121        # Check for valid output credentials
122        # XML tags input as keywords expected - check minimum
123        # required are present for SessionMgr connect response
124        if 'proxyCert' not in self and 'sessCookie' not in self:           
125
126            # If no proxy cert or session cookie then it must be an error
127            if 'errMsg' not in self:
128                raise ConnectRespError(\
129                "Connect response document must contain: \"proxyCert\"" + \
130                " or \"sessCookie\" keywords")
131   
132
133#_____________________________________________________________________________
134class AddUserReqError(XMLMsgError):   
135    """Exception handling for NDG SessionMgr WS connect request class."""
136    pass
137
138
139#_____________________________________________________________________________
140class AddUserReq(XMLMsg):
141    """For client to Session Manager WS addUser(): formats inputs for request
142    into XML and encrypts.
143   
144    For Session Manager enables decryption of result"""
145   
146    # Override base class class variables
147    xmlTagTmpl = {  "userName":    "",
148                    "pPhrase":     "",
149                    "encrCert":    ""    }
150                       
151
152    def __init__(self, **xmlMsgKeys):
153        """XML for sending encrypted credentials to Session Manager connect
154       
155        xmlMsgKeys:    keywords for XMLMsg super-class.  If XML tags are
156                       input as keywords then 'userName' and 'pPhrase'
157                       must be input as the bare minimum required for
158                       SessionMgr addUser request.
159        """
160       
161                               
162        # Check for encrypted text or valid credentials
163        if 'encrXMLtxt' not in xmlMsgKeys and 'xmlTxt' not in xmlMsgKeys:           
164
165            # XML tags input as keywords expected - check minimum
166            # required are present for SessionMgr connect request
167            if 'userName' not in xmlMsgKeys and 'pPhrase' not in xmlMsgKeys:
168                raise AddUserReqError(\
169                    "Credentials must include \"userName\" and \"pPhrase\"")
170               
171        # Allow user credentials to be access like dictionary keys
172        super(self.__class__, self).__init__(**xmlMsgKeys)
173     
174
175#_____________________________________________________________________________
176class AddUserRespError(XMLMsgError):   
177    """Exception handling for NDG SessionMgr WS addUser response class."""
178    pass
179
180
181#_____________________________________________________________________________
182class AddUserResp(XMLMsg):
183    """For client to Session Manager WS connect(): formats addUser response
184    from SessionMgr.
185   
186    For client, enables decryption of response"""
187   
188    # Override base class class variables
189    xmlTagTmpl = {"errMsg": ""}
190                       
191
192    def __init__(self, **xmlMsgKeys):
193        """XML for returning error status from Session Manager addUser()
194       
195        xmlMsgKeys:    keywords for XMLMsg super-class.  If XML tags are
196                       input as keywords then 'proxyCert' or 'sessCookie'
197                       must be set.
198        """
199               
200        # Allow user credentials to be access like dictionary keys
201        super(self.__class__, self).__init__(**xmlMsgKeys)
202       
203                               
204        # Check valid output
205        if 'errMsg' not in self:           
206
207            # XML tags input as keywords expected - check minimum
208            # required are present for SessionMgr connect response
209            raise AddUserRespError(\
210                "AddUser response must contain \"errMsg\" keyword")
211       
212
213#_____________________________________________________________________________
214class AuthorisationReqError(XMLMsgError):   
215    """Exception handling for NDG SessionMgr WS authorisation request class.
216    """
217    pass
218
219
220#_____________________________________________________________________________
221class AuthorisationReq(XMLMsg):
222    """For client to Session Manager WS reqAuthorisation(): formats inputs for
223    request into XML and encrypts.
224   
225    Session Manager enables decryption of result"""
226   
227    # Override base class class variables
228    xmlTagTmpl = {  "sessID":                 "",
229                    "encrSessMgrWSDLuri":     "",
230                    "encrSessMgrPubKeyURI":   "",
231                    "proxyCert":              "",
232                    "aaWSDL":                 "",
233                    "aaPubKey":               "",
234                    "reqRole":                "",
235                    "mapFromTrustedHosts":    "",
236                    "rtnExtAttCertList":      "",
237                    "extAttCertList":         "",
238                    "extTrustedHostList":     "",
239                    "encrCert":               ""    }
240
241    def __init__(self, **xmlMsgKeys):
242        """XML for sending encrypted credentials to Session Manager
243        authorisation request
244       
245        xmlMsgKeys:    keywords for XMLMsg super-class.  If XML tags are
246                       input as keywords then 'userName' and 'pPhrase' or
247                       'proxyCert' or 'sessID' must be input as the bare
248                       minimum required for SessionMgr connect request.
249        """
250                       
251        # Allow user credentials to be access like dictionary keys
252        super(self.__class__, self).__init__(**xmlMsgKeys)
253
254                               
255        # Check for encrypted text or valid credentials
256        if 'sessID' not in self and \
257           'encrSessMgrWSDLuri' not in self and \
258           'encrSessMgrPubKeyURI' not in self:
259            if 'proxyCert' not in self:
260                raise AuthorisationReqError(\
261                    "Authorisation request must include the credentials: " + \
262                    "\"sessID\", \"encrSessMgrWSDLuri\" and " + \
263                    "\"encrSessMgrPubKeyURI\" or \"proxyCert\"")
264               
265        if 'aaWSDL' not in self:           
266            raise AuthorisationReqError(\
267                "Authorisation request must include: \"aaWSDL\"")
268
269
270#_____________________________________________________________________________
271class AuthorisationRespError(XMLMsgError):   
272    """Exception handling for NDG SessionMgr WS connect response class."""
273    pass
274
275
276#_____________________________________________________________________________
277class AuthorisationResp(XMLMsg):
278    """For client to Session Manager WS connect(): formats authorisation
279    response from SessionMgr.
280   
281    For client, enables decryption of response"""
282   
283    # Override base class class variables
284    xmlTagTmpl = {  "attCert":           "",
285                    "extAttCertList":    "",
286                    "statCode":          "",
287                    "errMsg":            ""    }
288
289    accessGranted = 'AccessGranted'   
290    accessDenied = 'AccessDenied'
291    accessError = 'AccessError'
292
293
294    def __init__(self, **xmlMsgKeys):
295        """XML for receiving output from Session Manager authorisation call
296       
297        xmlMsgKeys:    keywords for XMLMsg super-class.  If XML tags are
298                       input as keywords then 'errMsg' or 'statCode'
299                       must be set.
300        """       
301       
302        # Allow user credentials to be access like dictionary keys
303        super(self.__class__, self).__init__(**xmlMsgKeys)
304       
305                               
306        # Check for valid output credentials
307        if 'errMsg' not in self and 'statCode' not in self:           
308
309            # XML tags input as keywords expected - check minimum
310            # required are present for SessionMgr connect response
311            raise AuthorisationRespError(\
312                "Authorisation response must contain: \"errMsg\"" + \
313                " or \"statCode\" keywords")
314
315
316    #_________________________________________________________________________
317    def update(self, attCert=None, extAttCertList=None, **xmlTags):
318        """Override base class implementation to include extra code
319        to allow setting of extAttCertList tag"""
320
321        def setAttCert(attCert=None):
322            if isinstance(attCert, basestring):
323                return AttCertParse(attCert)
324           
325            elif isinstance(attCert, AttCert):
326                return attCert
327           
328            elif attCert is not None:
329                raise TypeError(\
330                    "extAttCertList must contain string or AttCert types")
331
332        if extAttCertList is not None:
333            if isinstance(extAttCertList, list):
334                 
335                # Join into single string and filter out XML headers as 
336                # ElementTree doesn't like these nested into a doc                       
337                extAttCertList = map(setAttCert, extAttCertList)
338           
339            elif extAttCertList == '':
340                extAttCertList = []
341            else:
342                raise TypeError("\"extAttCertList\" must be of list type")
343               
344        # Call super class update with revised attribute certificate list
345        super(self.__class__, self).update(attCert=setAttCert(attCert),
346                                           extAttCertList=extAttCertList,
347                                           **xmlTags)
348
349
350    #_________________________________________________________________________
351    def updateXML(self, **xmlTags):
352        """Override base class implementation to include extra code
353        to include extAttCertList tag"""
354       
355        # Update dictionary
356        self.update(**xmlTags)
357       
358        # Create XML formatted string ready for encryption
359        try:
360            xmlTxt = self.xmlHdr + os.linesep + \
361                "<" + self.__class__.__name__ + ">" + os.linesep
362               
363            for tag in xmlTags:
364                if isinstance(self[tag], AttCert):
365                    # Attribute Certificate received from Attribute Authority
366                    #
367                    # Remove any XML header -
368                    # update() call will have converted val to AttCert type
369                    text = self[tag].asString(stripXMLhdr=True)
370                 
371                elif isinstance(self[tag], list):
372                    # List of Attribute Certificates from other trusted hosts
373                    #
374                    # Call AttCert parse and return as Element type to append
375                    # as branches
376                    text = os.linesep.join([ac.asString(stripXMLhdr=True) \
377                                            for ac in self[tag]]) 
378               
379                elif isinstance(self[tag], bool):
380                    text = "%d" % self[tag]
381                   
382                elif self[tag] is None:
383                    # Leave out altogether if set to None
384                    continue
385                else:       
386                    text = self[tag]
387
388                xmlTxt += "    <%s>%s</%s>%s" % (tag, text, tag, os.linesep)
389               
390            xmlTxt += "</" + self.__class__.__name__ + ">" + os.linesep   
391            self.xmlTxt = xmlTxt
392
393        except Exception, e:
394            raise XMLMsgError("Creating XML: %s" % e)
395
396
397    #_________________________________________________________________________
398    def parseXML(self):
399        """Override base class implementation to include extra code
400        to parse extAttCertList tag"""
401       
402        rootElem = super(self.__class__, self).parseXML(rtnRootElem=True)
403
404        extAttCertListElem = rootElem.find("extAttCertList")
405        if extAttCertListElem:
406
407            # Add attribute certificates as AttCert instances
408            try:
409                self['extAttCertList'] = \
410                    [AttCertParse(ElementTree.tostring(elem)) \
411                    for elem in extAttCertListElem]
412                   
413            except Exception, e:
414                raise AuthorisationRespError(\
415                    "Error parsing Ext. Attribute Certificate List: "+str(e))                               
416
417   
Note: See TracBrowser for help on using the repository browser.