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

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

ndg.security.server/ndg/security/server/conf/sessionMgrProperties.xml:

  • don't comment out hostname instead include by default

ndg.security.server/ndg/security/server/SessionMgr/init.py:

  • fixed comment typo

ndg.security.server/ndg/security/server/MyProxy.py:

to prevent setting of OpenSSL config file without the required file name and
directory path.

ndg.security.test/ndg/security/test/AttCert/attCertTest.cfg,
ndg.security.test/ndg/security/test/AttCert/AttCertTest.py:

  • fixed unit tests for AC signature verification. certFilePathList can now

be set to include CA certs. to verify the X.509 cert. used in the signature

ndg.security.test/ndg/security/test/SessionMgr/SessionMgrClientTest.py:

  • fix: extAttCertList is no longer returned in getAttCert calls to SM client.

ndg.security.test/ndg/security/test/SessionMgr/sessionMgrClientTest.cfg:

  • tests with services on glue

ndg.security.common/ndg/security/common/XMLSec.py:

  • fixed verifyEnvelopedSignature so that it is now possible to verify the

X.509 cert. in the signature against it's issuing CA cert.

ndg.security.common/ndg/security/common/SessionMgr/init.py:

  • modified getAttCert call so that extAttCertList is no longer passed back in

the returned tuple but is instead included as an attribute of the
AttributeRequestDenied? exception type.

  • updated pydoc for getAttCert method

ndg.security.common/ndg/security/common/AttAuthority/init.py:

  • typo fix - doesn't affect execution

ndg.security.common/ndg/security/common/CredWallet.py:

  • updates to getAttCert call pydoc
  • and getAttCert exception handling
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# Determine https http transport
28import urlparse, httplib
29from ZSI.wstools.Utility import HTTPResponse
30
31from AttAuthority_services import AttAuthorityServiceLocator
32from ndg.security.common.wsSecurity import SignatureHandler
33from ndg.security.common.AttCert import AttCert, AttCertParse
34from ndg.security.common.m2CryptoSSLUtility import HTTPSConnection, \
35    HostCheck
36
37
38#_____________________________________________________________________________
39class AttAuthorityClientError(Exception):
40    """Exception handling for AttributeAuthorityClient class"""
41
42#_____________________________________________________________________________
43class AttributeRequestDenied(Exception):
44    """Raise when a getAttCert call to the AA is denied"""
45
46
47#_____________________________________________________________________________
48class AttAuthorityClient(object):
49    """Client interface to Attribute Authority web service"""
50   
51    #_________________________________________________________________________
52    def __init__(self, 
53                 uri=None, 
54                 tracefile=None,
55                 sslCACertList=[],
56                 sslCACertFilePathList=[],
57                 sslPeerCertCN=None, 
58                 setSignatureHandler=True,
59                 **signatureHandlerKw):
60        """
61        @type uri: string
62        @keyword uri: URI for Attribute Authority WS.  Setting it will also
63        initialise the Service Proxy
64                                         
65        @keyword tracefile: set to file object such as sys.stderr to give
66        extra WS debug information
67       
68        @type sslCACertList: list
69        @keyword sslCACertList: This keyword is for use with SSL connections
70        only.  Set a list of one ore more CA certificates.  The peer cert.
71        must verify against at least one of these otherwise the connection
72        is dropped.
73       
74        @type sslCACertFilePathList: list
75        @keyword sslCACertFilePathList: the same as the above except CA certs
76        can be passed as a list of file paths to read from
77       
78        @type sslPeerCertCN: string
79        @keyword sslPeerCertCN: set an alternate CommonName to match with peer
80        cert.  This keyword is for use with SSL connections only.
81                     
82        @type setSignatureHandler: bool
83        @param setSignatureHandler: flag to determine whether to apply
84        WS-Security Signature Handler or not
85
86        @type signatureHandlerKw: dict
87        @param signatureHandlerKw: keywords to configure signature handler"""
88
89        self.__srv = None
90        self.__uri = None
91        self._transdict = {}       
92       
93        if uri:
94            self.__setURI(uri)
95
96        if sslPeerCertCN:
97            self.__setSSLPeerCertCN(sslPeerCertCN)
98       
99        if sslCACertList:
100            self.__setSSLCACertList(sslCACertList)
101        elif sslCACertFilePathList:
102            self.__setSSLCACertFilePathList(sslCACertFilePathList)
103       
104        # WS-Security Signature handler - set only if any of the keywords were
105        # set
106        if setSignatureHandler:
107            self.__signatureHandler = SignatureHandler(**signatureHandlerKw)
108        else:
109            self.__signatureHandler = None
110           
111        self.__tracefile = tracefile
112       
113        # Instantiate Attribute Authority WS proxy
114        if self.__uri:
115            self.initService()
116       
117
118    #_________________________________________________________________________
119    def __setURI(self, uri):
120        """Set URI for service
121        @type uri: string
122        @param uri: URI for service to connect to"""
123        if not isinstance(uri, basestring):
124            raise AttAuthorityClientError, \
125                        "Attribute Authority WSDL URI must be a valid string"
126       
127        self.__uri = uri
128        try:
129            scheme = urlparse.urlparse(self.__uri)[0]
130        except TypeError:
131            raise AttributeAuthorityClientError, \
132                "Error parsing transport type from URI"
133               
134        if scheme == "https":
135            self._transport = HTTPSConnection
136        else:
137            self._transport = None
138               
139    uri = property(fset=__setURI, doc="Set Attribute Authority URI")
140
141
142    #_________________________________________________________________________
143    def __setSSLPeerCertCN(self, cn):
144        """For use with HTTPS connections only.  Specify the Common
145        Name to match with Common Name of the peer certificate.  This is not
146        needed if the peer cert CN = peer hostname"""
147        if self._transport != HTTPSConnection:
148            return
149       
150        if self._transdict.get('postConnectionCheck'):
151            self._transdict['postConnectionCheck'].peerCertCN = cn
152        else:
153            self._transdict['postConnectionCheck'] = HostCheck(peerCertCN=cn)
154
155    sslPeerCertCN = property(fset=__setSSLPeerCertCN, 
156doc="for https connections, set CN of peer cert if other than peer hostname")
157
158
159    #_________________________________________________________________________
160    def __setSSLCACertList(self, caCertList):
161        """For use with HTTPS connections only.  Specify CA certs to one of
162        which the peer cert must verify its signature against"""
163        if self._transport != HTTPSConnection:
164            return
165       
166        if self._transdict.get('postConnectionCheck'):
167            self._transdict['postConnectionCheck'].caCertList = caCertList
168        else:
169            self._transdict['postConnectionCheck'] = \
170                                            HostCheck(caCertList=caCertList)
171
172    sslCACertList = property(fset=__setSSLCACertList, 
173doc="for https connections, set list of CA certs from which to verify peer cert")
174
175
176    #_________________________________________________________________________
177    def __setSSLCACertFilePathList(self, caCertFilePathList):
178        """For use with HTTPS connections only.  Specify CA certs to one of
179        which the peer cert must verify its signature against"""
180        if self._transport != HTTPSConnection:
181            return
182       
183        if self._transdict.get('postConnectionCheck'):
184            self._transdict['postConnectionCheck'].caCertFilePathList = \
185                                                            caCertFilePathList
186        else:
187            self._transdict['postConnectionCheck'] = \
188                            HostCheck(caCertFilePathList=caCertFilePathList)
189
190    sslCACertFilePathList = property(fset=__setSSLCACertFilePathList, 
191doc="for https connections, set list of CA cert files from which to verify peer cert")
192
193   
194    #_________________________________________________________________________
195    def __setSignatureHandler(self, signatureHandler):
196        """Set SignatureHandler object property method - set to None to for no
197        digital signature and verification"""
198        if signatureHandler is not None and \
199           not isinstance(signatureHandler, signatureHandler):
200            raise AttributeError, \
201    "Signature Handler must be %s type or None for no message security" % \
202        "ndg.security.common.wsSecurity.SignatureHandler"
203                           
204        self.__signatureHandler = signatureHandler
205   
206
207    #_________________________________________________________________________
208    def __getSignatureHandler(self):
209        "Get SignatureHandler object property method"
210        return self.__signatureHandler
211   
212    signatureHandler = property(fget=__getSignatureHandler,
213                                fset=__setSignatureHandler,
214                                doc="SignatureHandler object")
215   
216       
217    #_________________________________________________________________________
218    def initService(self, uri=None):
219        """Set the WS proxy for the Attribute Authority
220       
221        @type uri: string
222        @keyword uri: URI for service to invoke"""
223       
224        if uri:
225            self.__setURI(uri)
226
227        # WS-Security Signature handler object is passed to binding
228        try:
229            locator = AttAuthorityServiceLocator()
230            self.__srv = locator.getAttAuthority(self.__uri, 
231                                         sig_handler=self.__signatureHandler,
232                                         tracefile=self.__tracefile,
233                                         transport=self._transport,
234                                         transdict=self._transdict)
235        except HTTPResponse, e:
236            raise AttAuthorityClientError, \
237                "Error initialising service for \"%s\": %s %s" % \
238                (self.__uri, e.status, e.reason)
239
240                                   
241    #_________________________________________________________________________
242    def getHostInfo(self):
243        """Get host information for the data provider which the
244        Attribute Authority represents
245       
246        @rtype: dict
247        @return: dictionary of host information derived from the Attribute
248        Authority's map configuration
249        """
250
251        try:
252            hostname, aaURI, loginURI = self.__srv.getHostInfo()
253        except httplib.BadStatusLine, e:
254            raise AttAuthorityClientError, "HTTP bad status line: %s" % e
255
256        hostInfo = {}
257        hostInfo[hostname] = {'aaURI': aaURI, 'loginURI': loginURI}
258
259        return hostInfo
260
261                                   
262    #_________________________________________________________________________
263    def getTrustedHostInfo(self, role=None):
264        """Get list of trusted hosts for an Attribute Authority
265       
266        @type role: string
267        @param role: get information for trusted hosts that have a mapping to
268        this role
269       
270        @rtype: dict
271        @return: dictionary of host information indexed by hostname derived
272        from the map configuration"""
273           
274        try:
275            trustedHosts = self.__srv.getTrustedHostInfo(role)
276        except httplib.BadStatusLine, e:
277            raise AttAuthorityClientError, "HTTP bad status line: %s" % e
278
279        # Convert into dictionary form as used by AttAuthority class
280        trustedHostInfo = {}
281        for trustedHost in trustedHosts:
282            hostname = trustedHost.get_element_hostname()
283           
284            trustedHostInfo[hostname] = \
285            {
286                'aaURI':    trustedHost.get_element_aaURI(),
287                'loginURI': trustedHost.get_element_loginURI(),
288                'role':     trustedHost.get_element_roleList()
289            }
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        except httplib.BadStatusLine, e:
334            raise AttAuthorityClientError, "HTTP bad status line: %s" % e
335       
336        if sAttCert:
337            return AttCertParse(sAttCert)
338        else:
339            raise AttributeRequestDenied, msg
340
341                                   
342    #_________________________________________________________________________
343    def getX509Cert(self):
344        """Retrieve the X.509 certificate of the Attribute Authority
345       
346        @rtype: string
347        @return X.509 certificate for Attribute Authority"""
348       
349        try:
350            return self.__srv.getX509Cert()               
351        except httplib.BadStatusLine, e:
352            raise AttAuthorityClientError, "HTTP bad status line: %s" % e
Note: See TracBrowser for help on using the repository browser.