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

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

python/ndg.security.common/ndg/security/common/ca/init.py,
python/ndg.security.server/ndg/security/server/MyProxy.py,
python/ndg.security.server/ndg/security/server/ca/init.py: simplify settings for
_createCertReq DN default.

python/ndg.security.test/ndg/security/test/ca/caClientTest.cfg: altered connection
settings.

python/ndg.security.test/ndg/security/test/ca/caClientTest.py: try passing in a
grid-cert-request generated request for temporary testing.

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