source: TI12-security/trunk/python/NDG/AttAuthorityIO.py @ 1018

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

Tests/SecurityClientTest?.py: mods to run on gabriel.

Tests/security.py: added functionality to get trusted host info.

dist/NDG-Security-0.66.tar.gz: new distro for testing on gabriel.

conf/mapConfig.xml: added loginURI tag for each trusted host - indicate URI for user login useful for forwarding of
login page from remote site.

NDG/AttAuthorityIO.py: include loginURI tag in trusted host info response message.

NDG/SecurityCGI.py: include functionality to get trusted host info from an AttAuthority?

NDG/AttAuthority.py: added loginURI tag for getTrustedHostInfo call.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1"""NDG Attribute Authority 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
14reposID = '$Id$'
15       
16from XMLMsg import *
17
18# For use with AuthorisationResp class
19from AttCert import *
20
21#_____________________________________________________________________________
22class AuthorisationReqError(XMLMsgError):   
23    """Exception handling for NDG AttAuthority WS authorisation request class.
24    """
25    pass
26
27
28#_____________________________________________________________________________
29class AuthorisationReq(XMLMsg):
30    """For client to Attribute Authority WS reqAuthorisation(): formats inputs
31    for request into XML and encrypts.
32   
33    Attribute Authority enables decryption of result"""
34   
35    # Override base class class variables
36    xmlTagTmpl = {  "proxyCert":    "",
37                    "userAttCert":  "",
38                    "encrCert":     ""    }
39                   
40    xmlMandTags = ["proxyCert"]
41                               
42                               
43    #_________________________________________________________________________
44    def update(self, userAttCert=None, **xmlTags):
45        """Override base class implementation to include extra code
46        to allow setting of userAttCert tag"""
47
48        if userAttCert:
49            if isinstance(userAttCert, basestring):
50                attCert = AttCertParse(userAttCert)
51           
52            elif isinstance(userAttCert, AttCert):
53                attCert = userAttCert
54            else:
55                raise TypeError(\
56                    "userAttCert keyword must contain string or AttCert type")
57                       
58        else:
59            attCert = None
60               
61        # Call super class update with revised attribute certificate list
62        super(self.__class__, self).update(userAttCert=attCert, **xmlTags)
63                                           
64                                           
65    #_________________________________________________________________________
66    def updateXML(self, **xmlTags):
67        """Override base class implementation to include extra code
68        to allow attribute certificate to be set from a string or AttCert
69        type"""
70       
71        # Update dictionary
72        self.update(**xmlTags)
73       
74        # Create XML formatted string ready for encryption
75        try:
76            xmlTxt = self.xmlHdr + os.linesep + \
77                "<" + self.__class__.__name__ + ">" + os.linesep
78               
79            for tag, val in self.items():
80                if tag == "userAttCert":
81                    # Remove any XML header -
82                    # update() call will have converted val to AttCert type
83                    val = val.asString(stripXMLhdr=True)
84                   
85                xmlTxt += "    <%s>%s</%s>%s" % (tag, val, tag, os.linesep)
86                   
87            xmlTxt += "</" + self.__class__.__name__ + ">" + os.linesep   
88            self.xmlTxt = xmlTxt
89           
90        except Exception, e:
91            raise XMLMsgError("Creating XML: %s" % e)
92
93
94    #_________________________________________________________________________
95    def parseXML(self):
96        """Override base class implementation to include extra code
97        to parse userAttCert tag - if left with the default, elementtree
98        adds extra "ns0" namespaces which invalidate the signature(!)"""
99       
100        rootElem = super(self.__class__, self).parseXML(rtnRootElem=True)
101        if 'userAttCert' in self:
102
103            # Convert attribute certificate to AttCert instance
104            try:
105                attCertPat = re.compile(\
106                    '<attributeCertificate>.*</attributeCertificate>', re.S)
107                attCertTxt = attCertPat.findall(self.xmlTxt)[0]
108               
109                self['userAttCert'] = AttCertParse(attCertTxt)
110               
111            except Exception, e:
112                raise AuthorisationRespError(\
113                    "Error parsing Attribute Certificate: " + str(e)) 
114
115
116#_____________________________________________________________________________
117class AuthorisationRespError(XMLMsgError):   
118    """Exception handling for NDG AttAuthority WS connect response class."""
119    pass
120
121
122#_____________________________________________________________________________
123class AuthorisationResp(XMLMsg):
124    """For client to Attribute Authority WS reqAuthorisation(): formats
125    authorisation response from AttAuthority.
126   
127    For client, enables decryption of response"""
128   
129    # Override base class class variables
130    xmlTagTmpl = {  "credential":        "",
131                    "statCode":          "",
132                    "errMsg":            ""    }
133
134    xmlMandTags = ["statCode"]
135   
136    accessGranted = 'AccessGranted'   
137    accessDenied = 'AccessDenied'
138    accessError = 'AccessError'
139
140
141    def __init__(self, **xmlMsgKeys):
142        """XML for receiving output from Attribute Authority authorisation
143        call
144       
145        xmlMsgKeys:    keywords for XMLMsg super-class.  If XML tags are
146                       input as keywords then 'errMsg' or 'statCode'
147                       must be set.
148        """       
149       
150        # Allow credentials to be accessed like dictionary keys
151        super(self.__class__, self).__init__(**xmlMsgKeys)
152       
153        if 'credential' not in self and 'errMsg' not in self:
154            raise AuthorisationRespError(\
155                                'Expecting "credential" or "errMsg" keywords')
156                               
157                               
158    #_________________________________________________________________________
159    def update(self, credential=None, **xmlTags):
160        """Override base class implementation to include extra code
161        to allow setting of extAttCertList tag"""
162
163        if credential:
164            if isinstance(credential, basestring):
165                attCert = AttCertParse(credential)
166           
167            elif isinstance(credential, AttCert):
168                attCert = credential
169            else:
170                raise TypeError(\
171                    "credential keyword must contain string or AttCert type")
172                       
173        else:
174            attCert = None
175               
176        # Call super class update with revised attribute certificate list
177        super(self.__class__, self).update(credential=attCert, **xmlTags)
178                                           
179                                           
180    #_________________________________________________________________________
181    def updateXML(self, **xmlTags):
182        """Override base class implementation to include extra code
183        to allow attribute certificate to be set from a string or AttCert
184        type"""
185       
186        # Update dictionary
187        self.update(**xmlTags)
188       
189        # Create XML formatted string ready for encryption
190        try:
191            xmlTxt = self.xmlHdr + os.linesep + \
192                "<" + self.__class__.__name__ + ">" + os.linesep
193               
194            for tag, val in self.items():
195                if tag == "credential":
196                    # Remove any XML header -
197                    # update() call will have converted val to AttCert type
198                    val = val.asString(stripXMLhdr=True)
199                   
200                xmlTxt += "    <%s>%s</%s>%s" % (tag, val, tag, os.linesep)
201                   
202            xmlTxt += "</" + self.__class__.__name__ + ">" + os.linesep   
203            self.xmlTxt = xmlTxt
204           
205#            rootNode = ElementTree.Element(self.__class__.__name__)
206#            rootNode.tail = os.linesep
207#           
208#            for tag in xmlTags:
209#                # ElementTree tostring doesn't like bool types
210#                elem = ElementTree.SubElement(rootNode, tag)
211#                elem.tail = os.linesep
212#               
213#                if isinstance(self[tag], bool):
214#                    elem.text = "%d" % self[tag]
215#               
216#                elif tag == 'credential':
217#
218#                    # str() will convert self[tag] correctly if it is an
219#                    # AttCert type
220#                    attCertElem = ElementTree.XML(str(self[tag]))
221#                    attCertElem.tail = os.linesep
222#                    elem.append(attCertElem)
223#                else:       
224#                    elem.text = self[tag]
225#                     
226#            self.xmlTxt = self.xmlHdr + os.linesep + \
227#                                                ElementTree.tostring(rootNode)
228        except Exception, e:
229            raise XMLMsgError("Creating XML: %s" % e)
230
231
232    #_________________________________________________________________________
233    def parseXML(self):
234        """Override base class implementation to include extra code
235        to parse extAttCertList tag - if left with the default, elementtree
236        adds extra "ns0" namespaces which invalidate the signature(!)"""
237       
238        rootElem = super(self.__class__, self).parseXML(rtnRootElem=True)
239        if 'credential' in self:
240
241            # Convert attribute certificate to AttCert instance
242            try:
243                attCertPat = re.compile(\
244                    '<attributeCertificate>.*</attributeCertificate>', re.S)
245                attCertTxt = attCertPat.findall(self.xmlTxt)[0]
246               
247                self['credential'] = AttCertParse(attCertTxt)
248               
249            except Exception, e:
250                raise AuthorisationRespError(\
251                    "Error parsing Attribute Certificate: " + str(e)) 
252
253
254#_____________________________________________________________________________
255class TrustedHostInfoReqError(XMLMsgError):   
256    """Exception handling for NDG AttAuthority WS GetTrustedHostInfo request
257    class."""
258    pass
259
260
261#_____________________________________________________________________________
262class TrustedHostInfoReq(XMLMsg):
263    """For client to Attribute Authority WS GetTrustedHostInfo(): formats
264    inputs for request into XML and encrypts.
265   
266    Attribute Authority enables decryption of result"""
267   
268    # Override base class class variables
269    xmlTagTmpl = {"role": "", "encrCert": ""}
270
271
272#_____________________________________________________________________________
273class TrustedHostInfoRespError(XMLMsgError):   
274    """Exception handling for NDG AttAuthority WS GetTrustedHostInfo response
275    class."""
276    pass
277
278
279#_____________________________________________________________________________
280class TrustedHostInfoResp(XMLMsg):                             
281    """For client to Attribute Authority WS getTrustedInfo(): formats
282    response from AttAuthority.
283   
284    For client, enables decryption of response"""
285   
286    # Override base class class variables
287    xmlTagTmpl = {"trustedHosts": "", "errMsg": ""}
288
289
290    def __init__(self, **xmlMsgKeys):
291        """XML for receiving output from Attribute Authority authorisation
292        call
293       
294        xmlMsgKeys:    keywords for XMLMsg super-class.  If XML tags are
295                       input as keywords then 'errMsg' or 'statCode'
296                       must be set.
297        """       
298       
299        # Allow user credentials to be access like dictionary keys
300        super(self.__class__, self).__init__(**xmlMsgKeys)
301       
302       
303    #_________________________________________________________________________
304    def updateXML(self, **xmlTags):
305        """Override base class implementation to include extra code
306        to allow attribute certificate to be set from a string or AttCert
307        type"""
308       
309        # Update dictionary
310        self.update(**xmlTags)
311       
312        # Create XML formatted string ready for encryption
313        try:
314            xmlTxt = self.xmlHdr + os.linesep + \
315                "<" + self.__class__.__name__ + ">" + os.linesep
316               
317            if "trustedHosts" in xmlTags:
318                xmlTxt += "    <trustedHosts>%s" % os.linesep
319               
320                for host, hostInfo in xmlTags['trustedHosts'].items():
321                    xmlTxt += "        <trusted name=\"%s\">" % host
322                    xmlTxt += os.linesep
323                    xmlTxt += "            <wsdl>%s</wsdl>" % hostInfo['wsdl']
324                    xmlTxt += "            <loginURI>%s</loginURI>" % \
325                                                        hostInfo['loginURI']
326                    xmlTxt += os.linesep
327                    xmlTxt += "            <roleSet>" + os.linesep
328                    xmlTxt += ''.join(["                <role>%s</role>%s" % \
329                                        (role, os.linesep) \
330                                        for role in hostInfo['role']])
331                    xmlTxt += "            </roleSet>" + os.linesep                   
332                    xmlTxt += "        </trusted>" + os.linesep
333
334                xmlTxt += "    </trustedHosts>%s" % os.linesep
335
336            if "errMsg" in xmlTags:
337                xmlTxt += "    <errMsg>%s</errMsg>%s" % \
338                                            (xmlTags['errMsg'], os.linesep)
339                   
340            xmlTxt += "</" + self.__class__.__name__ + ">" + os.linesep   
341            self.xmlTxt = xmlTxt
342           
343
344        except Exception, e:
345            raise XMLMsgError("Creating XML: %s" % e)
346
347
348    #_________________________________________________________________________
349    def parseXML(self):
350        """Override base class implementation to include extra code
351        to parse trusted hosts info"""
352       
353        rootElem = super(self.__class__, self).parseXML(rtnRootElem=True)
354        self['trustedHosts'] = {}
355       
356        trustedHostsElem = rootElem.find('trustedHosts')
357        if not trustedHostsElem:
358            # No trusted hosts were found
359            return
360         
361        for trusted in trustedHostsElem:
362            try:
363                host = trusted.items()[0][1]
364               
365                # Add key for trusted host name
366                self['trustedHosts'][host] = {}
367               
368                # Add WSDL URI, loginURI and role set for that host
369                self['trustedHosts'][host]['wsdl'] = \
370                                            trusted.find('wsdl').text.strip()
371                                           
372                self['trustedHosts'][host]['loginURI'] = \
373                                        trusted.find('loginURI').text.strip()
374                                           
375                self['trustedHosts'][host]['role'] = \
376                    [role.text.strip() for role in trusted.find('roleSet')]
377                 
378            except Exception, e:
379                raise TrustedHostInfoRespError(\
380                "Error parsing tag \"%s\" in trusted host info response: %s" \
381                % (trusted.tag, str(e)))
382 
383
384#_____________________________________________________________________________
385class PubKeyReqError(XMLMsgError):   
386    """Exception handling for NDG SessionMgr WS getPubKey request class."""
387    pass
388
389
390#_____________________________________________________________________________
391class PubKeyReq(XMLMsg):
392    """For client to Session Manager WS getPubKey(): formats inputs for
393    request into XML"""   
394    pass
395
396
397#_____________________________________________________________________________
398class PubKeyRespError(XMLMsgError):   
399    """Exception handling for NDG SessionMgr WS getPubKey response class."""
400    pass
401
402
403#_____________________________________________________________________________
404class PubKeyResp(XMLMsg):
405    """For client to Session Manager WS getPubKey(): formats getPubKey
406    response from SessionMgr"""
407   
408    # Override base class class variables
409    xmlTagTmpl = {"pubKey": "", "errMsg": ""}
410                       
411
412    def __init__(self, **xmlMsgKeys):
413        """XML for receiving credentials from Session Manager getPubKey call
414       
415        xmlMsgKeys:    keywords for XMLMsg super-class.  If XML tags are
416                       input as keywords then 'proxyCert' or 'sessCookie'
417                       must be set.                       
418        """       
419       
420        # Allow user credentials to be access like dictionary keys
421        super(self.__class__, self).__init__(**xmlMsgKeys)
422       
423                               
424        # Check for valid output credentials
425        # XML tags input as keywords expected - check minimum
426        # required are present for SessionMgr getPubKey response
427        if 'pubKey' not in self and 'errMsg' not in self:           
428            raise PubKeyRespError(\
429                "PubKey response document must contain: \"pubKey\"" + \
430                " or \"errMsg\" keywords")
431               
Note: See TracBrowser for help on using the repository browser.