source: TI12-security/trunk/python/ndg.security.common/ndg/security/common/AttAuthority/__init__.py @ 2289

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

python/ndg.security.server/ndg/security/server/AttAuthority/server-config.tac:
modified soap_getAttCert to allow for unsigned client messages. If the
useSignatureHandler flag is not set, then the certificate passed in to
AttAuthority?.getAttCert is the userCert element of the SOAP message.

This is a useful capability if both client and service are behind a firewall
and message security is not required.

python/ndg.security.server/ndg/security/server/AttAuthority/init.py,
python/ndg.security.server/ndg/security/server/conf/attAuthorityProperties.
xml,
python/ndg.security.test/ndg/security/test/AttAuthority/siteAAttAuthorityProperties.xml,
python/ndg.security.test/ndg/security/test/AttAuthority/siteBAttAuthorityProperties.xml:
added useSignatureHandler element to list of elements in the properties file.
If this is not set, then the service will not apply signature or signature
verification to messages.

python/ndg.security.test/ndg/security/test/AttAuthority/AttAuthorityClientTest.py: use dictionary get() rather then [key] for signature keywords. This enables
them to be omitted in the config file so as to switch off the signature handler.

python/ndg.security.test/ndg/security/test/AttAuthority/attAuthorityClientTest.cfg: experimented with omitting signature PKI settings.

python/ndg.security.test/ndg/security/test/MyProxy/myProxyProperties.xml:
set serverCNprefix element to host/ for this MyProxy? installations server cert.

python/ndg.security.test/ndg/security/test/MyProxy/myProxyClientTest.cfg:
altered for account on this machine.

python/ndg.security.common/setup.py: slight change to Python 2.5 check for
ElementTree inclusion

python/ndg.security.common/ndg/security/common/AttAuthority/init.py:
SignatureHandler? is now optional. It's left as None if none of the signature
keywords are set via init. It can be set later as the signatureHandler
property now has set capability enabled.

Line 
1#!/usr/bin/env python
2"""NDG Security Attribute Authority client - client interface classes to the
3Attribute Authority.  These have been separated from their
4original location in the SecurityClient since they have the
5unusual place of being required by both client and server
6NDG security packages.  For the server side they are required
7as the CredWallet invoked by the Session Manager acts as a
8client to Attribute Authorities when negotiating the required
9Attribute Certificate.
10
11Make requests for Attribute Certificates used for authorisation
12
13NERC Data Grid Project
14
15@author P J Kershaw 17/11/06
16
17@copyright (C) 2006 CCLRC & NERC
18
19@license This software may be distributed under the terms of the Q Public
20License, version 1.0 or later.
21"""
22__all__ = [
23    'AttAuthority_services',
24    'AttAuthority_services_types',
25    ]
26
27# Handling for public key retrieval
28import tempfile
29
30from AttAuthority_services import AttAuthorityServiceLocator
31from ndg.security.common.wsSecurity import SignatureHandler
32from ndg.security.common.AttCert import AttCert, AttCertParse
33
34#_____________________________________________________________________________
35class AttAuthorityClientError(Exception):
36    """Exception handling for AttributeAuthorityClient class"""
37
38#_____________________________________________________________________________
39class AttributeRequestDenied(Exception):
40    """Raise when a getAttCert call to the AA is denied"""
41
42
43#_____________________________________________________________________________
44class AttAuthorityClient(object):
45    """Client interface to Attribute Authority web service"""
46   
47    #_________________________________________________________________________
48    def __init__(self, uri=None, tracefile=None, **signatureHandlerKw):
49        """
50        @type uri: string
51        @keyword uri: URI for Attribute Authority WS.  Setting it will also
52        initialise the Service Proxy
53                                         
54        @keyword tracefile: set to file object such as sys.stderr to give
55        extra WS debug information"""
56
57        self.__srv = None
58        self.__uri = None
59        self.__srvCertTempFile = None
60       
61       
62        if uri:
63            self.__setURI(uri)
64
65        # WS-Security Signature handler - set only if any of the keywords were set
66        if max(signatureHandlerKw.values()):
67            self.__signatureHandler = SignatureHandler(**signatureHandlerKw)
68        else:
69            self.__signatureHandler = None
70           
71        self.__tracefile = tracefile
72
73         
74        # Instantiate Attribute Authority WS proxy
75        if self.__uri:
76            self.initService()
77       
78
79    #_________________________________________________________________________
80    def __setURI(self, uri):
81       
82        if not isinstance(uri, basestring):
83            raise AttAuthorityClientError, \
84                        "Attribute Authority WSDL URI must be a valid string"
85       
86        self.__uri = uri
87       
88    uri = property(fset=__setURI, doc="Set Attribute Authority WSDL URI")
89
90
91    #_________________________________________________________________________
92    def __setSignatureHandler(self, signatureHandler):
93        """Set SignatureHandler object property method - set to None to for no
94        digital signature and verification"""
95        if signatureHandler is not None and \
96           not isinstance(signatureHandler, signatureHandler):
97            raise AttributeError, \
98    "Signature Handler must be %s type or None for no message security" % \
99        "ndg.security.common.wsSecurity.SignatureHandler"
100                           
101        self.__signatureHandler = signatureHandler
102   
103
104    #_________________________________________________________________________
105    def __getSignatureHandler(self):
106        "Get SignatureHandler object property method"
107        return self.__signatureHandler
108   
109    signatureHandler = property(fget=__getSignatureHandler,
110                                fset=__setSignatureHandler,
111                                doc="SignatureHandler object")
112
113
114    #_________________________________________________________________________
115    def __setSrvCertFilePath(self, srvCertFilePath):
116       
117        if not isinstance(srvCertFilePath, basestring):
118            raise AttAuthorityClientError, \
119                "Attribute Authority public key URI must be a valid string"
120       
121        self.__srvCertFilePath = srvCertFilePath
122       
123    srvCertFilePath = property(fset=__setSrvCertFilePath,
124                              doc="Set Attribute Authority public key URI")
125
126 
127    #_________________________________________________________________________
128    def __setClntCertFilePath(self, clntCertFilePath):
129       
130        if not isinstance(clntCertFilePath, basestring):
131            raise AttAuthorityClientError, \
132                "Client public key file path must be a valid string"
133       
134        self.__clntCertFilePath = clntCertFilePath
135       
136        try:
137            self.__clntCert = open(self.__clntCertFilePath).read()
138           
139        except IOError, (errNo, errMsg):
140            raise AttAuthorityClientError, \
141                    "Reading certificate file \"%s\": %s" % \
142                    (self.__clntCertFilePath, errMsg)
143                               
144        except Exception, e:
145            raise AttAuthorityClientError, \
146                                    "Reading certificate file \"%s\": %s" % \
147                                    (self.__clntCertFilePath, str(e))
148       
149    clntCertFilePath = property(fset=__setClntCertFilePath,
150                                doc="File path for client public key")
151
152 
153    #_________________________________________________________________________
154    def __setClntPriKeyFilePath(self, clntPriKeyFilePath):
155       
156        if not isinstance(clntPriKeyFilePath, basestring):
157            raise AttAuthorityClientError(\
158                "Client public key file path must be a valid string")
159       
160        self.__clntPriKeyFilePath = clntPriKeyFilePath
161       
162    clntPriKeyFilePath = property(fset=__setClntPriKeyFilePath,
163                                  doc="File path for client private key")
164
165 
166    #_________________________________________________________________________
167    def __setClntPriKeyPwd(self, clntPriKeyPwd):
168       
169        if not isinstance(clntPriKeyPwd, basestring):
170            raise SessionMgrClientError, \
171                        "Client private key password must be a valid string"
172       
173        self.__clntPriKeyPwd = clntPriKeyPwd
174       
175    clntPriKeyPwd = property(fset=__setClntPriKeyPwd,
176                         doc="Password protecting client private key file")
177
178
179    #_________________________________________________________________________
180    def __getSrvCert(self):
181        """Retrieve the public key from the URI"""
182       
183        # Don't proceed unless URI was set - user may have set public key via
184        # srvCertFilePath instead
185        if self.__srvCertFilePath is not None:
186            return
187               
188        try:
189            self.__srvCertTempFile = tempfile.NamedTemporaryFile()
190           
191            cert = self.getX509Cert()
192            open(self.__srvCertTempFile.name, "w").write(cert)
193           
194            self.__srvCertFilePath = self.__srvCertTempFile.name
195           
196        except IOError, (errNo, errMsg):
197            raise AttAuthorityClientError, \
198                                "Writing public key to temp \"%s\": %s" % \
199                                (self.__srvCertTempFile.name, errMsg)                                                                     
200        except Exception, e:
201            raise AttAuthorityClientError, "Retrieving Attribute Authority "+\
202                                          "public key: %s" % str(e)
203   
204       
205    #_________________________________________________________________________
206    def initService(self, uri=None):
207        """Set the WS proxy for the Attribute Authority
208       
209        @type uri: string
210        @param uri: URI for service to invoke"""
211       
212        if uri:
213            self.__setURI(uri)
214
215        # WS-Security Signature handler object is passed to binding
216        try:
217            locator = AttAuthorityServiceLocator()
218            self.__srv = locator.getAttAuthority(self.__uri, 
219                                         sig_handler=self.__signatureHandler,
220                                         tracefile=self.__tracefile)
221        except HTTPResponse, e:
222            raise AttAuthorityClientError, \
223                "Error initialising WSDL Service for \"%s\": %s %s" % \
224                (self.__uri, e.status, e.reason)
225           
226        except Exception, e:
227            raise AttAuthorityClientError, \
228                "Initialising WSDL Service for \"%s\": %s" % \
229                 (self.__uri, str(e))
230
231                                   
232    #_________________________________________________________________________
233    def getHostInfo(self):
234        """Get host information for the data provider which the
235        Attribute Authority represents
236       
237        @rtype: dict
238        @return: dictionary of host information derived from the Attribute
239        Authority's map configuration
240        """
241
242        try:   
243            hostname, aaURI, loginURI = self.__srv.getHostInfo()
244
245        except Exception, e:
246            raise AttAuthorityClientError, \
247                                    "Retrieving host information: " + str(e)
248       
249        hostInfo = {}
250       
251        hostInfo[hostname] = {}       
252        hostInfo[hostname]['aaURI'] = aaURI
253        hostInfo[hostname]['loginURI'] = loginURI
254
255        return hostInfo
256
257                                   
258    #_________________________________________________________________________
259    def getTrustedHostInfo(self, role=None):
260        """Get list of trusted hosts for an Attribute Authority
261       
262        @type role: string
263        @param role: get information for trusted hosts that have a mapping to
264        this role
265       
266        @rtype: dict
267        @return: dictionary of host information indexed by hostname derived
268        from the map configuration"""
269           
270        try:   
271            trustedHosts = self.__srv.getTrustedHostInfo(role)
272
273        except Exception, e:
274            raise AttAuthorityClientError, \
275                                "Getting trusted host information: " + str(e)
276
277        # Convert into dictionary form as used by AttAuthority class
278        trustedHostInfo = {}
279        for trustedHost in trustedHosts:
280            hostname = trustedHost.get_element_hostname()
281           
282            trustedHostInfo[hostname] = {}
283           
284            trustedHostInfo[hostname]['aaURI'] = \
285                                            trustedHost.get_element_aaURI()
286            trustedHostInfo[hostname]['loginURI'] = \
287                                            trustedHost.get_element_loginURI()
288            trustedHostInfo[hostname]['role'] = \
289                                            trustedHost.get_element_roleList()
290           
291        return trustedHostInfo
292   
293
294    #_________________________________________________________________________
295    def getAttCert(self, userId=None, userCert=None, userAttCert=None):
296        """Request attribute certificate from NDG Attribute Authority Web
297        Service.
298       
299        @type userId: string
300        @keyword userId: DN of the X.509 certificate used in SOAP digital
301        signature corresponds to the *holder* of the Attribute Certificate
302        that is issued.  Set this additional field to specify an alternate
303        user ID to associate with the AC.  This is useful in the case where,
304        as in the DEWS project, the holder will be a server cert. rather than
305        a user proxy cert.
306       
307        If this keword is omitted, userId in the AC will default to the same
308        value as the holder DN.
309       
310        @type userCert: string
311        @keyword userCert: certificate corresponding to proxy private key and
312        proxy cert used to sign the request.  Enables server to establish
313        chain of trust proxy -> user cert -> CA cert.  If a standard
314        private key is used to sign the request, this argument is not
315        needed.
316       
317        @type userAttCert: string / AttCert
318        @keyword userAttCert: user attribute certificate from which to make a
319        mapped certificate at the target attribute authority.  userAttCert
320        must have been issued from a trusted host to the target.  This is not
321        necessary if the user is registered at the target Attribute Authority.
322       
323        @rtype ndg.security.common.AttCert.AttCert
324        @return attribute certificate for user.  iIf access is refused,
325        AttributeRequestDenied is raised"""
326
327        # Ensure cert is serialized before passing over web service interface
328        if isinstance(userAttCert, AttCert):
329            userAttCert = userAttCert.toString()
330           
331        try: 
332            sAttCert, msg = self.__srv.getAttCert(userId,userCert,userAttCert) 
333           
334        except Exception, e:
335            raise AttAuthorityClientError, \
336                                "Requesting attribute certificate: " + str(e)
337
338        if sAttCert:
339            return AttCertParse(sAttCert)
340        else:
341            raise AttributeRequestDenied, msg
342
343                                   
344    #_________________________________________________________________________
345    def getX509Cert(self):
346        """Retrieve the X.509 certificate of the Attribute Authority
347       
348        @rtype: string
349        @return X.509 certificate for Attribute Authority"""
350       
351        try:   
352            return self.__srv.getX509Cert()               
353       
354        except Exception, e:
355            raise AttAuthorityClientError, \
356                                    "Error retrieving public key: " + str(e) 
Note: See TracBrowser for help on using the repository browser.