source: TI12-security/trunk/python/ndg.security.common/ndg/security/common/ca/__init__.py @ 4129

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI12-security/trunk/python/ndg.security.common/ndg/security/common/ca/__init__.py@4129
Revision 4129, 11.5 KB checked in by cbyrom, 11 years ago (diff)

General refactoring and updating of code, including:

Removal of refC14nKw and singnedInfoC14nKw keywords in wsssecurity session manager config
(the refC14nInclNS and signedInfoC14nInclNS keywords are sufficient);
Creation of new DOM signature handler class, dom.py, based on the wsSecurity
class;
Abstraction of common code between dom.py and etree.py into new parent
class, BaseSignatureHandler?.py.
Fixing and extending use of properties in the SignatureHandler? code.
Fixing a few bugs with the original SignatureHandler? code.
Updating of test cases to new code/code structure.

  • Property svn:keywords set to Id
Line 
1"""NDG Security Certificate Authority client - client interface classes to the
2Certificate Authority. 
3
4NERC Data Grid Project
5"""
6__author__ = "P J Kershaw"
7__date__ = "17/11/06"
8__copyright__ = "(C) 2007 STFC & NERC"
9__contact__ = "P.J.Kershaw@rl.ac.uk"
10__license__ = \
11"""This software may be distributed under the terms of the Q Public
12License, version 1.0 or later."""
13__contact__ = "P.J.Kershaw@rl.ac.uk"
14__revision__ = "$Id$"
15
16__all__ = [
17    'CertificateAuthority_services',
18    'CertificateAuthority_services_types',
19    ]
20
21# Handling for public key retrieval
22import tempfile
23from ZSI.wstools.Utility import HTTPResponse
24from M2Crypto import X509, RSA, EVP, m2
25
26from CertificateAuthority_services import CertificateAuthorityServiceLocator
27from ndg.security.common.wssecurity.dom import SignatureHandler
28from ndg.security.common.openssl import OpenSSLConfig
29
30
31#_____________________________________________________________________________
32class CertificateAuthorityClientError(Exception):
33    """Exception handling for CertificateAuthorityClient class"""
34
35
36#_____________________________________________________________________________
37class CertificateAuthorityClient(object):
38    """Client interface to Certificate Authority web service
39   
40    @ctype _certReqDNparamName: tuple
41    @cvar _certReqDNparamName: names of parameters needed to generate a
42    certificate request e.g. CN, OU etc."""
43
44    _certReqDNparamName = ('O', 'OU')
45   
46    #_________________________________________________________________________
47    def __init__(self, 
48                 uri=None, 
49                 tracefile=None,
50                 openSSLConfigFilePath=None, 
51                 **signatureHandlerKw):
52        """
53        @type uri: string
54        @param uri: URI for Attribute Authority WS.  Setting it will also
55        initialise the Service Proxy
56                                         
57        @param tracefile: set to file object such as sys.stderr to give
58        extra WS debug information
59       
60        @type **signatureHandlerKw: dict
61        @param **signatureHandlerKw: keywords for SignatureHandler class"""
62
63        self.__srv = None
64        self.__uri = None
65       
66
67        # Set-up parameter names for certificate request
68        self.__openSSLConfig = OpenSSLConfig(filePath=openSSLConfigFilePath)
69
70       
71        if uri:
72            self.__setURI(uri)
73
74        # WS-Security Signature handler
75        self.__signatureHandler = SignatureHandler(**signatureHandlerKw)
76           
77        self.__tracefile = tracefile
78
79         
80        # Instantiate Attribute Authority WS proxy
81        if self.__uri:
82            self.initService()
83       
84
85    #_________________________________________________________________________
86    def __setURI(self, uri):
87       
88        if not isinstance(uri, basestring):
89            raise CertificateAuthorityClientError, \
90                        "Attribute Authority WSDL URI must be a valid string"
91       
92        self.__uri = uri
93       
94    uri = property(fset=__setURI, doc="Set Attribute Authority WSDL URI")
95
96
97    #_________________________________________________________________________
98    def __getOpenSSLConfig(self):
99        "Get OpenSSLConfig object property method"
100        return self.__openSSLConfig
101   
102    openSSLConfig = property(fget=__getOpenSSLConfig,
103                             doc="OpenSSLConfig object")
104
105
106    #_________________________________________________________________________
107    def __getSignatureHandler(self):
108        "Get SignatureHandler object property method"
109        return self.__signatureHandler
110   
111    signatureHandler = property(fget=__getSignatureHandler,
112                                doc="SignatureHandler object")
113
114
115    #_________________________________________________________________________
116    def __setSrvCertFilePath(self, srvCertFilePath):
117       
118        if not isinstance(srvCertFilePath, basestring):
119            raise CertificateAuthorityClientError, \
120                "Attribute Authority public key URI must be a valid string"
121       
122        self.__srvCertFilePath = srvCertFilePath
123       
124    srvCertFilePath = property(fset=__setSrvCertFilePath,
125                              doc="Set Attribute Authority public key URI")
126
127 
128    #_________________________________________________________________________
129    def __setClntCertFilePath(self, clntCertFilePath):
130       
131        if not isinstance(clntCertFilePath, basestring):
132            raise CertificateAuthorityClientError, \
133                "Client public key file path must be a valid string"
134       
135        self.__clntCertFilePath = clntCertFilePath
136       
137        try:
138            self.__clntCert = open(self.__clntCertFilePath).read()
139           
140        except IOError, (errNo, errMsg):
141            raise CertificateAuthorityClientError, \
142                    "Reading certificate file \"%s\": %s" % \
143                    (self.__clntCertFilePath, errMsg)
144                               
145        except Exception, e:
146            raise CertificateAuthorityClientError, \
147                                    "Reading certificate file \"%s\": %s" % \
148                                    (self.__clntCertFilePath, str(e))
149       
150    clntCertFilePath = property(fset=__setClntCertFilePath,
151                                doc="File path for client public key")
152
153 
154    #_________________________________________________________________________
155    def __setClntPriKeyFilePath(self, clntPriKeyFilePath):
156       
157        if not isinstance(clntPriKeyFilePath, basestring):
158            raise CertificateAuthorityClientError(\
159                "Client public key file path must be a valid string")
160       
161        self.__clntPriKeyFilePath = clntPriKeyFilePath
162       
163    clntPriKeyFilePath = property(fset=__setClntPriKeyFilePath,
164                                  doc="File path for client private key")
165
166 
167    #_________________________________________________________________________
168    def __setClntPriKeyPwd(self, clntPriKeyPwd):
169       
170        if not isinstance(clntPriKeyPwd, basestring):
171            raise SessionMgrClientError, \
172                        "Client private key password must be a valid string"
173       
174        self.__clntPriKeyPwd = clntPriKeyPwd
175       
176    clntPriKeyPwd = property(fset=__setClntPriKeyPwd,
177                         doc="Password protecting client private key file")
178
179       
180    #_________________________________________________________________________
181    def initService(self, uri=None):
182        """Set the WS proxy for the Attribute Authority
183       
184        @type uri: string
185        @param uri: URI for service to invoke"""
186       
187        if uri:
188            self.__setURI(uri)
189
190        # WS-Security Signature handler object is passed to binding
191        try:
192            locator = CertificateAuthorityServiceLocator()
193            self.__srv = locator.getCertificateAuthority(self.__uri, 
194                                         sig_handler=self.__signatureHandler,
195                                         tracefile=self.__tracefile)
196        except HTTPResponse, e:
197            raise CertificateAuthorityClientError, \
198                "Error initialising WSDL Service for \"%s\": %s %s" % \
199                (self.__uri, e.status, e.reason)
200           
201        except Exception, e:
202            raise CertificateAuthorityClientError, \
203                "Initialising WSDL Service for \"%s\": %s" % \
204                 (self.__uri, str(e))
205                 
206                 
207    #_________________________________________________________________________       
208    def _createCertReq(self, CN, nBitsForKey=1024, messageDigest="md5"):
209        """
210        Create a certificate request.
211       
212        @param CN: Common Name for certificate - effectively the same as the
213        username for the MyProxy credential
214        @param nBitsForKey: number of bits for private key generation -
215        default is 1024
216        @param messageDigest: message disgest type - default is MD5
217        @return tuple of certificate request PEM text and private key PEM text
218        """
219       
220        # Check all required certifcate request DN parameters are set               
221        # Create certificate request
222        req = X509.Request()
223   
224        # Generate keys
225        key = RSA.gen_key(nBitsForKey, m2.RSA_F4)
226   
227        # Create public key object
228        pubKey = EVP.PKey()
229        pubKey.assign_rsa(key)
230       
231        # Add the public key to the request
232        req.set_version(0)
233        req.set_pubkey(pubKey)
234       
235        defaultReqDN = self.__openSSLConfig.reqDN       
236           
237        # Set DN
238        x509Name = X509.X509_Name()
239        x509Name.CN = CN
240        x509Name.OU = defaultReqDN['OU']
241        x509Name.O = defaultReqDN['O']
242                       
243        req.set_subject_name(x509Name)
244       
245        req.sign(pubKey, messageDigest)
246       
247        return req, key
248   
249                                   
250    #_________________________________________________________________________
251    def issueCert(self, 
252                  certReq=None, 
253                  CN=None, 
254                  openSSLConfigFilePath=None,
255                  **createCertReqKw):
256        """Send a certificate request to the CA for signing
257       
258        signCert([certReq=cr]|[CN=cn, openSSLConfigFilePath=p, **kw])
259       
260        @type certReq: M2Crypto.X509.Request
261        @param certReq: X.509 certificate request.  If omitted,
262        _createCertReq method is called to create a new public and private
263        key and a certificate request
264       
265        @type CN: string
266        @param CN: common name component of Distinguished Name for new
267        cert.  This keyword is ignored if certReq keyword is set.
268       
269        @type openSSLConfigFilePath: string
270        @param openSSLConfigFilePath: file path for OpenSSL configuration
271        file from which to get settings for Distinguished Name for new
272        certificate.  This keyword is ignored if certReq keyword is set.
273       
274        @type **createCertReqKw: dict
275        @param **createCertReqKw: keywords to call to _createCertReq - only
276        applies if certReq is not set.
277       
278        @rtype: tuple
279        @return: signed certificate and private key.  Private key will be
280        None if certReq keyword was passed in
281        """
282
283        priKey = None
284        if not certReq:
285            # Create the certificate request
286            certReq, priKey = self._createCertReq(CN, **createCertReqKw)
287       
288        try:   
289            cert = self.__srv.issueCert(certReq.as_pem())
290
291        except Exception, e:
292            raise CertificateAuthorityClientError, \
293                                            "Signing Certificate: " + str(e)     
294        return cert, priKey
295
296                                   
297    #_________________________________________________________________________
298    def revokeCert(self, x509Cert):
299        """Request that the CA revoke the given certificate
300       
301        @type x509Cert: string
302        @param x509Cert: X.509 certificate to be revoked"""
303           
304        try:   
305            self.__srv.revokeCert(x509Cert)
306
307        except Exception, e:
308            raise CertificateAuthorityClientError, \
309                                            "Revoking certificate: " + str(e)
310   
311
312    #_________________________________________________________________________
313    def getCRL(self):
314        """Request Certificate Revocation List (CRL) for the CA
315       
316        @rtype string
317        @return PEM encoded CRL"""
318
319        try: 
320            crl = self.__srv.getCRL() 
321           
322        except Exception, e:
323            raise CertificateAuthorityClientError, "Requesting CRL: " + str(e)
324
325        return crl
Note: See TracBrowser for help on using the repository browser.