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

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI12-security/trunk/python/NDG/AttAuthorityIO.py@930
Revision 930, 16.3 KB checked in by pjkersha, 13 years ago (diff)
  • Added Gatekeeper class.
  • Changed 'cvsID' ref global var in all files to 'reposID'
  • 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    def updateXML(self, **xmlTags):
303        """Override base class implementation to include extra code
304        to allow attribute certificate to be set from a string or AttCert
305        type"""
306       
307        # Update dictionary
308        self.update(**xmlTags)
309       
310        # Create XML formatted string ready for encryption
311        try:
312            xmlTxt = self.xmlHdr + os.linesep + \
313                "<" + self.__class__.__name__ + ">" + os.linesep
314               
315            if "trustedHosts" in xmlTags:
316                xmlTxt += "    <trustedHosts>%s" % os.linesep
317               
318                for host, hostInfo in xmlTags['trustedHosts'].items():
319                    xmlTxt += "        <trusted name=\"%s\">" % host
320                    xmlTxt += os.linesep
321                    xmlTxt += "            <wsdl>%s</wsdl>" % hostInfo['wsdl']
322                    xmlTxt += os.linesep
323                    xmlTxt += "            <roleSet>" + os.linesep
324                    xmlTxt += ''.join(["                <role>%s</role>%s" % \
325                                        (role, os.linesep) \
326                                        for role in hostInfo['role']])
327                    xmlTxt += "            </roleSet>" + os.linesep                   
328                    xmlTxt += "        </trusted>" + os.linesep
329
330                xmlTxt += "    </trustedHosts>%s" % os.linesep
331
332            if "errMsg" in xmlTags:
333                xmlTxt += "    <errMsg>%s</errMsg>%s" % \
334                                            (xmlTags['errMsg'], os.linesep)
335                   
336            xmlTxt += "</" + self.__class__.__name__ + ">" + os.linesep   
337            self.xmlTxt = xmlTxt
338           
339
340        except Exception, e:
341            raise XMLMsgError("Creating XML: %s" % e)
342
343
344    #_________________________________________________________________________
345    def parseXML(self):
346        """Override base class implementation to include extra code
347        to parse trusted hosts info"""
348       
349        rootElem = super(self.__class__, self).parseXML(rtnRootElem=True)
350        self['trustedHosts'] = {}
351       
352        trustedHostsElem = rootElem.find('trustedHosts')
353        if not trustedHostsElem:
354            raise TrustedHostInfoRespError(\
355            "\"trustedHosts\" tag not found in trusted host info response")
356         
357        for trusted in trustedHostsElem:
358            try:
359                host = trusted.items()[0][1]
360               
361                # Add key for trusted host name
362                self['trustedHosts'][host] = {}
363               
364                # Add WSDL URI and role set for that host
365                self['trustedHosts'][host]['wsdl'] = \
366                                            trusted.find('wsdl').text.strip()
367                                           
368                self['trustedHosts'][host]['role'] = \
369                    [role.text.strip() for role in trusted.find('roleSet')]
370                 
371            except Exception, e:
372                raise TrustedHostInfoRespError(\
373                "Error parsing tag \"%s\" in trusted host info response: %s" \
374                % (trusted.tag, str(e)))
375 
376
377#_____________________________________________________________________________
378class PubKeyReqError(XMLMsgError):   
379    """Exception handling for NDG SessionMgr WS getPubKey request class."""
380    pass
381
382
383#_____________________________________________________________________________
384class PubKeyReq(XMLMsg):
385    """For client to Session Manager WS getPubKey(): formats inputs for
386    request into XML"""   
387    pass
388
389
390#_____________________________________________________________________________
391class PubKeyRespError(XMLMsgError):   
392    """Exception handling for NDG SessionMgr WS getPubKey response class."""
393    pass
394
395
396#_____________________________________________________________________________
397class PubKeyResp(XMLMsg):
398    """For client to Session Manager WS getPubKey(): formats getPubKey
399    response from SessionMgr"""
400   
401    # Override base class class variables
402    xmlTagTmpl = {"pubKey": "", "errMsg": ""}
403                       
404
405    def __init__(self, **xmlMsgKeys):
406        """XML for receiving credentials from Session Manager getPubKey call
407       
408        xmlMsgKeys:    keywords for XMLMsg super-class.  If XML tags are
409                       input as keywords then 'proxyCert' or 'sessCookie'
410                       must be set.                       
411        """       
412       
413        # Allow user credentials to be access like dictionary keys
414        super(self.__class__, self).__init__(**xmlMsgKeys)
415       
416                               
417        # Check for valid output credentials
418        # XML tags input as keywords expected - check minimum
419        # required are present for SessionMgr getPubKey response
420        if 'pubKey' not in self and 'errMsg' not in self:           
421            raise PubKeyRespError(\
422                "PubKey response document must contain: \"pubKey\"" + \
423                " or \"errMsg\" keywords")
424               
Note: See TracBrowser for help on using the repository browser.