source: TI12-security/trunk/python/ndg.security.client/ndg/security/client/SimpleCAClient.py @ 2909

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI12-security/trunk/python/ndg.security.client/ndg/security/client/SimpleCAClient.py@2909
Revision 2909, 8.3 KB checked in by pjkersha, 13 years ago (diff)

Updated for epydoc: added double underscore vars module info

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
Line 
1"""Client to NDG SimpleCA WS
2
3NERC Data Grid Project
4"""
5__author__ = "P J Kershaw"
6__date__ = "17/11/06"
7__copyright__ = "(C) 2007 STFC & NERC"
8__license__ = \
9"""This software may be distributed under the terms of the Q Public
10License, version 1.0 or later."""
11__contact__ = "P.J.Kershaw@rl.ac.uk"
12__revision__ = '$Id$'
13
14import types
15import cElementTree as ElementTree
16from ZSI import ServiceProxy
17from ZSI.wstools.Utility import HTTPResponse
18import socket # handle socket errors from WS
19from CertReq import *
20
21
22#_____________________________________________________________________________
23class SimpleCAClientError(Exception):   
24    """Exception handling for NDG Certificate Request class."""
25   
26    def __init__(self, msg):
27        self.__msg = msg
28         
29    def __str__(self):
30        return self.__msg
31   
32
33
34
35#_____________________________________________________________________________
36class SimpleCAClient(dict):
37    """Implements ZSI client to SimpleCA WS"""
38
39    # valid configuration property keywords
40    __validKeys = ['wsdl',
41                   'xmlSigKeyFile',
42                   'xmlSigCertFile',
43                   'xmlSigCertPPhrase']
44   
45    def __init__(self,
46                 propFilePath=None,
47                 propElem=None,
48                 bInitSrvPx=True,
49                 **prop):       
50        """Initialise WS client to SimpleCA
51
52        propFilePath:       properties set via config file
53        bInitSrvPx:         initialise WS proxy - this can be called
54                            separately
55        **prop:             properties can be set via input keywords.  Nb.
56                            if a properties file has been set it's properties
57                            will override these settings"""
58
59
60        dict.__init__(self)
61       
62        # Properties set via input keywords
63        self.__prop = {}
64        self.setProperties(**prop)
65
66
67        # Properties set in file override if equivalent is present in
68        # properties file
69        if propFilePath or propElem:
70            self.readProperties(propFilePath, propElem)
71
72
73        # Set up Web Service proxy - if WSDL has been set input flag set also
74        if bInitSrvPx and 'wsdl' in self.__prop:
75            self.initSrvPx()
76        else:
77            self.__srvPx = None
78
79
80    def __call__(self):
81        """Return file properties dictionary"""
82        return self.__prop
83
84
85    def __repr__(self):
86        """Return file properties dictionary as representation"""
87        return repr(self.__prop)
88
89
90    def __str__(self):
91        """Return file properties dictionary as representation"""
92        return str(self.__prop)
93   
94   
95    #_________________________________________________________________________
96    # dict derived methods ...
97    #
98    # Nb. read only - no __setitem__() method
99    def __delitem__(self, key):
100        "SimpleCAClient Properties keys cannot be removed"       
101        raise SimpleCAError('Keys cannot be deleted from ' + \
102                            self.__class__.__name__)
103
104
105    def __getitem__(self, key):
106        self.__class__.__name__ + """ behaves as a data dictionary"""
107       
108        # Check input key
109        if key in self.__prop:
110            return self.__prop[key]
111        else:
112            raise SimpleCAClientError("Property with key '%s' not found"%key)
113
114
115    # 'in' operator
116    def __contains__(self, key):
117        return key in self.__prop
118       
119    def get(self, kw):
120        return self.__prop.get(kw)
121
122    def has_key(self, key):
123        return self.__prop.has_key(key)
124       
125    def clear(self):
126        raise SimpleCAClientError("Data cannot be cleared from " + \
127                                  self.__class__.__name__)
128   
129    def keys(self):
130        return self.__prop.keys()
131
132    def items(self):
133        return self.__prop.items()
134
135    def values(self):
136        return self.__prop.values()
137
138    # End of dict derived methods <--
139
140
141    #_________________________________________________________________________
142    def setProperties(self, **prop):
143        """Update existing properties from an input dictionary
144        Check input keys are valid names"""
145       
146        for key in prop.keys():
147            if key not in self.__validKeys:
148                raise SimpleCAClientError("Property name \"%s\" is invalid" %\
149                                          key)
150               
151        self.__prop.update(prop)
152
153           
154    #_________________________________________________________________________
155    def readProperties(self, propFilePath=None, propElem=None):
156        """Read XML properties from a file or cElementTree node
157
158        propFilePath|propElem
159
160        propFilePath: set to read from the specified file
161        propElem:     set to read beginning from a cElementTree node"""
162
163
164        if propFilePath is not None:
165
166            try:
167                tree = ElementTree.parse(propFilePath)
168            except IOError, e:
169                raise MyProxyError(\
170                                "Error parsing properties file \"%s\": %s" % \
171                                (e.filename, e.strerror))
172
173                propElem = tree.getroot()
174               
175            except Exception, e:
176                raise MyProxyError("Error parsing properties file: %s" % e)
177
178        if propElem is None:
179            raise MyProxyError("Root element for parsing is not defined")
180
181        # Get properties from file as a data dictionary cutting out leading
182        # and trailing white space
183        prop = {}
184        for elem in propElem:
185
186            # Check for environment variables in file paths
187            tagCaps = elem.tag.upper()
188            if 'FILE' in tagCaps or 'PATH' in tagCaps or 'DIR' in tagCaps:
189                elem.text = os.path.expandvars(elem.text)
190
191            prop[elem.tag] = elem.text.strip()
192
193        # Update any existing values       
194        self.setProperties(**prop)
195
196
197    #_________________________________________________________________________   
198    def initSrvPx(self):
199        """Initialise service proxy"""
200
201        if 'wsdl' not in self.__prop:
202            raise SimpleCAClientError, "Creating WS proxy: WSDL is not set"
203       
204        try:
205            self.__srvPx = ServiceProxy(self.__prop['wsdl'], use_wsdl=True)
206           
207        except HTTPResponse, e:
208            raise SimpleCAClientError, \
209                "Error initialising WSDL Service Proxy for \"%s\": %s %s" % \
210                (self.__prop['wsdl'], e.status, e.reason)
211
212        except Exception, e:
213            raise SimpleCAClientError, \
214                "Initialising WSDL Service Proxy for \"%s\": %s %s" % \
215                (self.__prop['wsdl'], e.status, e.reason)
216
217
218    #_________________________________________________________________________
219    def reqCert(self, certReqTxt=None, certReqFilePath=None, **prop):       
220        """Request certificate from SimpleCA WS"""
221
222        if self.__srvPx is None:
223            self.initSrvPx()
224
225       
226        # Add to existing properties
227        self.setProperties(**prop)
228
229               
230        try:
231            if certReqTxt:
232                pass               
233            elif certReqFilePath:
234                certReqTxt = open(certReqFilePath).read()
235            else:
236                raise Exception("No text or file path input")           
237               
238        except Exception, e:
239            raise SimpleCAClientError(\
240                                "Error reading certificate request: %s" % e) 
241
242        try:
243            certReq = CertReq(signingKeyFilePath=self.__prop['xmlSigKeyFile'],
244                              certFilePathList=self.__prop['xmlSigCertFile'])       
245            certReq.certReqTxt = certReqTxt
246           
247            # Sign certificate
248            certReq.sign(signingKeyPwd=self.__prop['xmlSigCertPPhrase'])
249           
250        except Exception, e:
251            raise SimpleCAClientError(\
252                            "Certificate request XML Signature: %s" % e)
253       
254       
255        try:         
256            resp = self.__srvPx.reqCert(usrCertReq=str(certReq))
257            if resp['errMsg']:
258                raise Exception(resp['errMsg'])
259
260            return resp['usrCert']
261
262        except socket.error, (errNum, errMsg):
263            raise SimpleCAClientError(\
264                "Error making certificate request: %s" % errMsg)
265           
266        except Exception, e:
267            raise SimpleCAClientError(\
268                "Error making certificate request: %s" % e)
Note: See TracBrowser for help on using the repository browser.