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

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

python/ndg.security.server/setup.py:

  • comment out Twisted from install - won't do egg install
  • updated long description

python/ndg.security.server/ndg/security/server/AttAuthority/server-config.tac:

  • added verifyingCertFilePath keyword to SignatureHandler? initialisation
  • added SSL capability

python/conf/attAuthorityProperties.xml,
python/ndg.security.test/ndg/security/test/AttAuthority/siteAAttAuthorityProperties.xml,
python/ndg.security.test/ndg/security/test/AttAuthority/siteBAttAuthorityProperties.xml,
python/ndg.security.server/ndg/security/server/AttAuthority/init.py:
added element names for reading SSL settings from properties file.

python/ndg.security.server/ndg/security/server/SessionMgr/server-config.tac:
added verifyingCertFilePath keyword to SignatureHandler? initialisation

python/conf/sessionMgrProperties.xml,
python/ndg.security.test/ndg/security/test/SessionMgr/sessionMgrProperties.xml,
python/ndg.security.server/ndg/security/server/SessionMgr/init.py:
added clntCertFile properties file element name for setting certificate for
verifying incoming SOAP messages.

python/ndg.security.server/ndg/security/server/SessionMgr/Makefile:
corrected typo.

python/ndg.security.server/ndg/security/server/MyProxy.py:
Put OpenSSLConfig and OpenSSLConfigError classes into their own package
'openssl' so that they can also be used by the Certificate Authority client.

python/www/html/certificateAuthority.wsdl,
python/ndg.security.server/ndg/security/server/ca/CertificateAuthority_services_server.py,
python/ndg.security.common/ndg/security/common/ca/CertificateAuthority_services_types.py,
python/ndg.security.common/ndg/security/common/ca/CertificateAuthority_services.py: updated operations to issueCert, revokeCert and getCRL.

python/ndg.security.test/ndg/security/test/AttAuthority/attAuthorityClientTest.cfg: changed address of service to connect to.

python/ndg.security.test/ndg/security/test/SessionMgr/sessionMgrClientTest.cfg:
alternative username connection settings

python/ndg.security.common/ndg/security/common/AttAuthority/init.py:
fixed typos in error message and comments.

ython/ndg.security.common/ndg/security/common/XMLSec.py: changed call to
getAttributeNodeNS to getAttributeNode for retrieving reference element URI
attribute.

python/ndg.security.common/ndg/security/common/ca/init.py: code for
Certificate Authority client

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

  • tidied up imports
  • added properties for setting keywords to reference and SignedInfo? C14N
  • changed sign method so that it is truely configurable allow use of inclusive or exclusive C14N based on the keywords set for reference and SignedInfo? C14N calls.
  • swapped calls to getAttributeNodeNS with getAttributeNode where appropriate.

java/DEWS/AttAuthority/appClientModule/META-INF/ibm-webservicesclient-bnd.xmi,
java/DEWS/AttAuthority/build/classes/META-INF/ibm-webservicesclient-bnd.xmi:
updated to that request generator correctly places X.509 cert in
BinarySecurityToken? element.

java/DEWS/AttAuthority/appClientModule/Main.java,
java/DEWS/AttAuthority/appClientjava/DEWS/AttAuthority/appClientModule/META-INF/ibm-webservicesclient-bnd.xmiModule/Main.java:
include calls to getX509Cert and getAttCert methods.

java/DEWS/SessionMgr/build/classes/META-INF/ibm-webservicesclient-bnd.xmi,
java/DEWS/SessionMgr/appClientModule/META-INF/ibm-webservicesclient-bnd.xmi:
updates for testing Session MAnager client

java/DEWS/SessionMgr/appClientModule/Main.java: switched username setting.

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
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, uri=None, tracefile=None, **signatureHandlerKw):
47        """
48        @type uri: string
49        @keyword uri: URI for Attribute Authority WS.  Setting it will also
50        initialise the Service Proxy
51                                         
52        @keyword tracefile: set to file object such as sys.stderr to give
53        extra WS debug information
54       
55        @type **signatureHandlerKw: dict
56        @param **signatureHandlerKw: keywords for SignatureHandler class"""
57
58        self.__srv = None
59        self.__uri = None
60       
61
62        # Set-up parameter names for certificate request
63        self.__certReqDNparam = {}
64
65       
66        if uri:
67            self.__setURI(uri)
68
69        # WS-Security Signature handler
70        self.__signatureHandler = SignatureHandler(**signatureHandlerKw)
71           
72        self.__tracefile = tracefile
73
74         
75        # Instantiate Attribute Authority WS proxy
76        if self.__uri:
77            self.initService()
78       
79
80    #_________________________________________________________________________
81    def __setURI(self, uri):
82       
83        if not isinstance(uri, basestring):
84            raise CertificateAuthorityClientError, \
85                        "Attribute Authority WSDL URI must be a valid string"
86       
87        self.__uri = uri
88       
89    uri = property(fset=__setURI, doc="Set Attribute Authority WSDL URI")
90
91
92    #_________________________________________________________________________
93    def __getSignatureHandler(self):
94        "Get SignatureHandler object property method"
95        return self.__signatureHandler
96   
97    signatureHandler = property(fget=__getSignatureHandler,
98                                doc="SignatureHandler object")
99
100
101    #_________________________________________________________________________
102    def __setSrvCertFilePath(self, srvCertFilePath):
103       
104        if not isinstance(srvCertFilePath, basestring):
105            raise CertificateAuthorityClientError, \
106                "Attribute Authority public key URI must be a valid string"
107       
108        self.__srvCertFilePath = srvCertFilePath
109       
110    srvCertFilePath = property(fset=__setSrvCertFilePath,
111                              doc="Set Attribute Authority public key URI")
112
113 
114    #_________________________________________________________________________
115    def __setClntCertFilePath(self, clntCertFilePath):
116       
117        if not isinstance(clntCertFilePath, basestring):
118            raise CertificateAuthorityClientError, \
119                "Client public key file path must be a valid string"
120       
121        self.__clntCertFilePath = clntCertFilePath
122       
123        try:
124            self.__clntCert = open(self.__clntCertFilePath).read()
125           
126        except IOError, (errNo, errMsg):
127            raise CertificateAuthorityClientError, \
128                    "Reading certificate file \"%s\": %s" % \
129                    (self.__clntCertFilePath, errMsg)
130                               
131        except Exception, e:
132            raise CertificateAuthorityClientError, \
133                                    "Reading certificate file \"%s\": %s" % \
134                                    (self.__clntCertFilePath, str(e))
135       
136    clntCertFilePath = property(fset=__setClntCertFilePath,
137                                doc="File path for client public key")
138
139 
140    #_________________________________________________________________________
141    def __setClntPriKeyFilePath(self, clntPriKeyFilePath):
142       
143        if not isinstance(clntPriKeyFilePath, basestring):
144            raise CertificateAuthorityClientError(\
145                "Client public key file path must be a valid string")
146       
147        self.__clntPriKeyFilePath = clntPriKeyFilePath
148       
149    clntPriKeyFilePath = property(fset=__setClntPriKeyFilePath,
150                                  doc="File path for client private key")
151
152 
153    #_________________________________________________________________________
154    def __setClntPriKeyPwd(self, clntPriKeyPwd):
155       
156        if not isinstance(clntPriKeyPwd, basestring):
157            raise SessionMgrClientError, \
158                        "Client private key password must be a valid string"
159       
160        self.__clntPriKeyPwd = clntPriKeyPwd
161       
162    clntPriKeyPwd = property(fset=__setClntPriKeyPwd,
163                         doc="Password protecting client private key file")
164
165
166    #_________________________________________________________________________       
167    def __setCertReqDNparam(self, dict):
168        '''certReqDNparam property set method - forces setting of certificate
169        request parameter names to valid values
170       
171        @param dict: dictionary of parameters'''
172       
173        invalidKw = [k for k in dict \
174                     if k not in self.__class__._certReqDNparamName]
175        if invalidKw:
176            raise CertificateAuthorityClientError, \
177    "Invalid certificate request keyword(s): %s.  Valid keywords are: %s" % \
178    (', '.join(invalidKw), ', '.join(self.__class__._certReqDNparamName))
179   
180        self.__certReqDNparam.update(dict)
181
182
183    #_________________________________________________________________________       
184    def __getCertReqDNparam(self):
185        """certReqDNparam property set method - for Certificate request
186        parameters dict"""
187        return self.__certReqDNparam
188   
189   
190    certReqDNparam = property(fset=__setCertReqDNparam,
191                            fget=__getCertReqDNparam,
192                            doc="Dictionary of parameters for cert. request")
193
194       
195    #_________________________________________________________________________
196    def initService(self, uri=None):
197        """Set the WS proxy for the Attribute Authority
198       
199        @type uri: string
200        @param uri: URI for service to invoke"""
201       
202        if uri:
203            self.__setURI(uri)
204
205        # WS-Security Signature handler object is passed to binding
206        try:
207            locator = CertificateAuthorityServiceLocator()
208            self.__srv = locator.getCertificateAuthority(self.__uri, 
209                                         sig_handler=self.__signatureHandler,
210                                         tracefile=self.__tracefile)
211        except HTTPResponse, e:
212            raise CertificateAuthorityClientError, \
213                "Error initialising WSDL Service for \"%s\": %s %s" % \
214                (self.__uri, e.status, e.reason)
215           
216        except Exception, e:
217            raise CertificateAuthorityClientError, \
218                "Initialising WSDL Service for \"%s\": %s" % \
219                 (self.__uri, str(e))
220                 
221                 
222    #_________________________________________________________________________       
223    def _createCertReq(self, CN, nBitsForKey=1024, messageDigest="md5"):
224        """
225        Create a certificate request.
226       
227        @param CN: Common Name for certificate - effectively the same as the
228        username for the MyProxy credential
229        @param nBitsForKey: number of bits for private key generation -
230        default is 1024
231        @param messageDigest: message disgest type - default is MD5
232        @return tuple of certificate request PEM text and private key PEM text
233        """
234       
235        # Check all required certifcate request DN parameters are set               
236        # Create certificate request
237        req = X509.Request()
238   
239        # Generate keys
240        key = RSA.gen_key(nBitsForKey, m2.RSA_F4)
241   
242        # Create public key object
243        pubKey = EVP.PKey()
244        pubKey.assign_rsa(key)
245       
246        # Add the public key to the request
247        req.set_version(0)
248        req.set_pubkey(pubKey)
249       
250        if self.__certReqDNparam:
251            certReqDNparam = self.__certReqDNparam
252        else:
253            defaultReqDN = self.__openSSLConf.getReqDN()
254           
255            certReqDNparam = {}
256            certReqDNparam['O'] = defaultReqDN['0.organizationName']
257            certReqDNparam['OU'] = defaultReqDN['0.organizationalUnitName']
258           
259        # Set DN
260        x509Name = X509.X509_Name()
261        x509Name.CN = CN
262        x509Name.OU = certReqDNparam['OU']
263        x509Name.O = certReqDNparam['O']
264        req.set_subject_name(x509Name)
265       
266        req.sign(pubKey, messageDigest)
267       
268        return (req.as_pem(), key.as_pem(cipher=None))
269   
270                                   
271    #_________________________________________________________________________
272    def signCert(self, 
273                 certReq=None, 
274                 CN=None, 
275                 opensslConfigFilePath=None,
276                 **createCertReqKw):
277        """Send a certificate request to the CA for signing
278       
279        signCert([certReq=cr]|[CN=cn, opensslConfigFilePath=p, **kw])
280       
281        @type certReq: M2Crypto.X509.Request
282        @keyword certReq: X.509 certificate request.  If omitted,
283        _createCertReq method is called to create a new public and private
284        key and a certificate request
285       
286        @type CN: string
287        @keyword CN: common name component of Distinguished Name for new
288        cert.  This keyword is ignored if certReq keyword is set.
289       
290        @type opensslConfigFilePath: string
291        @keyword opensslConfigFilePath: file path for OpenSSL configuration
292        file from which to get settings for Distinguished Name for new
293        certificate.  This keyword is ignored if certReq keyword is set.
294        @rtype: tuple
295        @return: signed certificate and private key.  Private key will be
296        None if certReq keyword was passed in
297        """
298
299        priKey = None
300        if not certReq:
301            # Create the certificate request
302            certReq, priKey = self._createCertReq(CN, **createCertReqKw)
303       
304        try:   
305            cert = self.__srv.signCert(certReq.as_pem())
306
307        except Exception, e:
308            raise CertificateAuthorityClientError, \
309                                            "Signing Certificate: " + str(e)     
310        return cert, priKey
311
312                                   
313    #_________________________________________________________________________
314    def revokeCert(self, x509Cert):
315        """Request that the CA revoke the given certificate
316       
317        @type x509Cert: string
318        @param x509Cert: X.509 certificate to be revoked"""
319           
320        try:   
321            self.__srv.revokeCert(x509Cert)
322
323        except Exception, e:
324            raise CertificateAuthorityClientError, \
325                                            "Revoking certificate: " + str(e)
326   
327
328    #_________________________________________________________________________
329    def getCRL(self):
330        """Request Certificate Revocation List (CRL) for the CA
331       
332        @rtype string
333        @return PEM encoded CRL"""
334
335        try: 
336            crl = self.__srv.getCRL() 
337           
338        except Exception, e:
339            raise CertificateAuthorityClientError, "Requesting CRL: " + str(e)
340
341        return crl
Note: See TracBrowser for help on using the repository browser.