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

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

* Change to AttCert? format and AA WS interface and AttAuthority? class for DEWS *

  • New userId element in Attribute Certificates + getAttCert call to an AA can specify a

user ID to be set in the returned AC.

python/ndg.security.server/ndg/security/server/AttAuthority/server-config.tac,
python/ndg.security.server/ndg/security/server/AttAuthority/AttAuthority_services_server.py,
python/ndg.security.common/ndg/security/common/AttAuthority/AttAuthority_services.py,
python/ndg.security.common/ndg/security/common/AttAuthority/AttAuthority_services_types.py,
python/www/html/attAuthority.wsdl:
added userId to WSDL interface.

python/ndg.security.server/ndg/security/server/AttAuthority/init.py:

  • added userId to getAttCert method.
  • changed refs to proxyCert to holderCert because cert meay not be a proxy
  • changed call to AttCert?.getRoles to AttCert?.roles
  • changed refs to userDN to userId

python/ndg.security.common/ndg/security/common/XMLSec.py: "ns1" is not needed for
reference C14N unsuppressed prefixes.

python/ndg.security.common/ndg/security/common/X509.py: made 'serialize' and 'deserialize'
aliases to serialise and deserialise methods respectively.

python/ndg.security.common/ndg/security/common/AttCert.py:

  • made AttCert? namespace a configurable class variable
  • changed all get/set attribute methods to private methods used by new-style class

properties.

  • updated setitem to use appropriate set* methods.
  • fix to setIssuerSerialNumber ref to 'issuerSerialNumber' instead of 'serialNumber'

python/ndg.security.common/ndg/security/common/AttAuthority/init.py: AA WS client -
added userId as keyword to getAttCert.

python/ndg.security.common/ndg/security/common/CredWallet.py: replace AttCert?.getRoles()
calls with AttCert?.roles property

python/ndg.security.test/ndg/security/test/AttAuthority/siteAUserRoles.py,
python/ndg.security.test/ndg/security/test/AttAuthority/siteBUserRoles.py:
swap refs to userDN with userId.

python/ndg.security.test/ndg/security/test/AttAuthority/AttAuthorityClientTest.py:
added new test for where an explicit userId is set.

python/ndg.security.test/ndg/security/test/AttAuthority/attAuthorityClientTest.cfg:
added userId parameter.

python/ndg.security.test/ndg/security/test/AttCert/AttCertTest.py: added tests for
property get calls.

python/ndg.security.test/ndg/security/test/MyProxy/Makefile: include call to MyProxy?
test to get proxy cert and private key.

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
66        self.__signatureHandler = SignatureHandler(**signatureHandlerKw)
67           
68        self.__tracefile = tracefile
69
70         
71        # Instantiate Attribute Authority WS proxy
72        if self.__uri:
73            self.initService()
74       
75
76    #_________________________________________________________________________
77    def __setURI(self, uri):
78       
79        if not isinstance(uri, basestring):
80            raise AttAuthorityClientError, \
81                        "Attribute Authority WSDL URI must be a valid string"
82       
83        self.__uri = uri
84       
85    uri = property(fset=__setURI, doc="Set Attribute Authority WSDL URI")
86
87
88    #_________________________________________________________________________
89    def __getSignatureHandler(self):
90        "Get SignatureHandler object property method"
91        return self.__signatureHandler
92   
93    signatureHandler = property(fget=__getSignatureHandler,
94                                doc="SignatureHandler object")
95
96
97    #_________________________________________________________________________
98    def __setSrvCertFilePath(self, srvCertFilePath):
99       
100        if not isinstance(srvCertFilePath, basestring):
101            raise AttAuthorityClientError, \
102                "Attribute Authority public key URI must be a valid string"
103       
104        self.__srvCertFilePath = srvCertFilePath
105       
106    srvCertFilePath = property(fset=__setSrvCertFilePath,
107                              doc="Set Attribute Authority public key URI")
108
109 
110    #_________________________________________________________________________
111    def __setClntCertFilePath(self, clntCertFilePath):
112       
113        if not isinstance(clntCertFilePath, basestring):
114            raise AttAuthorityClientError, \
115                "Client public key file path must be a valid string"
116       
117        self.__clntCertFilePath = clntCertFilePath
118       
119        try:
120            self.__clntCert = open(self.__clntCertFilePath).read()
121           
122        except IOError, (errNo, errMsg):
123            raise AttAuthorityClientError, \
124                    "Reading certificate file \"%s\": %s" % \
125                    (self.__clntCertFilePath, errMsg)
126                               
127        except Exception, e:
128            raise AttAuthorityClientError, \
129                                    "Reading certificate file \"%s\": %s" % \
130                                    (self.__clntCertFilePath, str(e))
131       
132    clntCertFilePath = property(fset=__setClntCertFilePath,
133                                doc="File path for client public key")
134
135 
136    #_________________________________________________________________________
137    def __setClntPriKeyFilePath(self, clntPriKeyFilePath):
138       
139        if not isinstance(clntPriKeyFilePath, basestring):
140            raise AttAuthorityClientError(\
141                "Client public key file path must be a valid string")
142       
143        self.__clntPriKeyFilePath = clntPriKeyFilePath
144       
145    clntPriKeyFilePath = property(fset=__setClntPriKeyFilePath,
146                                  doc="File path for client private key")
147
148 
149    #_________________________________________________________________________
150    def __setClntPriKeyPwd(self, clntPriKeyPwd):
151       
152        if not isinstance(clntPriKeyPwd, basestring):
153            raise SessionMgrClientError, \
154                        "Client private key password must be a valid string"
155       
156        self.__clntPriKeyPwd = clntPriKeyPwd
157       
158    clntPriKeyPwd = property(fset=__setClntPriKeyPwd,
159                         doc="Password protecting client private key file")
160
161
162    #_________________________________________________________________________
163    def __getSrvCert(self):
164        """Retrieve the public key from the URI"""
165       
166        # Don't proceed unless URI was set - user may have set public key via
167        # srvCertFilePath instead
168        if self.__srvCertFilePath is not None:
169            return
170               
171        try:
172            self.__srvCertTempFile = tempfile.NamedTemporaryFile()
173           
174            cert = self.getX509Cert()
175            open(self.__srvCertTempFile.name, "w").write(cert)
176           
177            self.__srvCertFilePath = self.__srvCertTempFile.name
178           
179        except IOError, (errNo, errMsg):
180            raise AttAuthorityClientError, \
181                                "Writing public key to temp \"%s\": %s" % \
182                                (self.__srvCertTempFile.name, errMsg)                                                                     
183        except Exception, e:
184            raise AttAuthorityClientError, "Retrieving Attribute Authority "+\
185                                          "public key: %s" % str(e)
186   
187       
188    #_________________________________________________________________________
189    def initService(self, uri=None):
190        """Set the WS proxy for the Attribute Authority
191       
192        @type uri: string
193        @param uri: URI for service to invoke"""
194       
195        if uri:
196            self.__setURI(uri)
197
198        # WS-Security Signature handler object is passed to binding
199        try:
200            locator = AttAuthorityServiceLocator()
201            self.__srv = locator.getAttAuthority(self.__uri, 
202                                         sig_handler=self.__signatureHandler,
203                                         tracefile=self.__tracefile)
204        except HTTPResponse, e:
205            raise AttAuthorityClientError, \
206                "Error initialising WSDL Service for \"%s\": %s %s" % \
207                (self.__uri, e.status, e.reason)
208           
209        except Exception, e:
210            raise AttAuthorityClientError, \
211                "Initialising WSDL Service for \"%s\": %s" % \
212                 (self.__uri, str(e))
213
214                                   
215    #_________________________________________________________________________
216    def getHostInfo(self):
217        """Get host information for the data provider which the
218        Attribute Authority represents
219       
220        @rtype: dict
221        @return: dictionary of host information derived from the Attribute
222        Authority's map configuration
223        """
224
225        try:   
226            hostname, aaURI, loginURI = self.__srv.getHostInfo()
227
228        except Exception, e:
229            raise AttAuthorityClientError, \
230                                    "Retrieving host information: " + str(e)
231       
232        hostInfo = {}
233       
234        hostInfo[hostname] = {}       
235        hostInfo[hostname]['aaURI'] = aaURI
236        hostInfo[hostname]['loginURI'] = loginURI
237
238        return hostInfo
239
240                                   
241    #_________________________________________________________________________
242    def getTrustedHostInfo(self, role=None):
243        """Get list of trusted hosts for an Attribute Authority
244       
245        @type role: string
246        @param role: get information for trusted hosts that have a mapping to
247        this role
248       
249        @rtype: dict
250        @return: dictionary of host information indexed by hostname derived
251        from the map configuration"""
252           
253        try:   
254            trustedHosts = self.__srv.getTrustedHostInfo(role)
255
256        except Exception, e:
257            raise AttAuthorityClientError, \
258                                "Getting trusted host information: " + str(e)
259
260        # Convert into dictionary form as used by AttAuthority class
261        trustedHostInfo = {}
262        for trustedHost in trustedHosts:
263            hostname = trustedHost.get_element_hostname()
264           
265            trustedHostInfo[hostname] = {}
266           
267            trustedHostInfo[hostname]['aaURI'] = \
268                                            trustedHost.get_element_aaURI()
269            trustedHostInfo[hostname]['loginURI'] = \
270                                            trustedHost.get_element_loginURI()
271            trustedHostInfo[hostname]['role'] = \
272                                            trustedHost.get_element_roleList()
273           
274        return trustedHostInfo
275   
276
277    #_________________________________________________________________________
278    def getAttCert(self, userId=None, userCert=None, userAttCert=None):
279        """Request attribute certificate from NDG Attribute Authority Web
280        Service.
281       
282        @type userId: string
283        @keyword userId: DN of the X.509 certificate used in SOAP digital
284        signature corresponds to the *holder* of the Attribute Certificate
285        that is issued.  Set this additional field to specify an alternate
286        user ID to associate with the AC.  This is useful in the case where,
287        as in the DEWS project, the holder will be a server cert. rather than
288        a user proxy cert.
289       
290        If this keword is omitted, userId in the AC will default to the same
291        value as the holder DN.
292       
293        @type userCert: string
294        @keyword userCert: certificate corresponding to proxy private key and
295        proxy cert used to sign the request.  Enables server to establish
296        chain of trust proxy -> user cert -> CA cert.  If a standard
297        private key is used to sign the request, this argument is not
298        needed.
299       
300        @type userAttCert: string / AttCert
301        @keyword userAttCert: user attribute certificate from which to make a
302        mapped certificate at the target attribute authority.  userAttCert
303        must have been issued from a trusted host to the target.  This is not
304        necessary if the user is registered at the target Attribute Authority.
305       
306        @rtype ndg.security.common.AttCert.AttCert
307        @return attribute certificate for user.  iIf access is refused,
308        AttributeRequestDenied is raised"""
309
310        # Ensure cert is serialized before passing over web service interface
311        if isinstance(userAttCert, AttCert):
312            userAttCert = userAttCert.toString()
313           
314        try: 
315            sAttCert, msg = self.__srv.getAttCert(userId,userCert,userAttCert) 
316           
317        except Exception, e:
318            raise AttAuthorityClientError, \
319                                "Requesting attribute certificate: " + str(e)
320
321        if sAttCert:
322            return AttCertParse(sAttCert)
323        else:
324            raise AttributeRequestDenied, msg
325
326                                   
327    #_________________________________________________________________________
328    def getX509Cert(self):
329        """Retrieve the X.509 certificate of the Attribute Authority
330       
331        @rtype: string
332        @return X.509 certificate for Attribute Authority"""
333       
334        try:   
335            return self.__srv.getX509Cert()               
336       
337        except Exception, e:
338            raise AttAuthorityClientError, \
339                                    "Error retrieving public key: " + str(e) 
Note: See TracBrowser for help on using the repository browser.