source: TI12-security/trunk/python/Tests/xmlsec/WS-Security/wsServer.py @ 1469

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI12-security/trunk/python/Tests/xmlsec/WS-Security/wsServer.py@1469
Revision 1469, 6.6 KB checked in by pjkersha, 13 years ago (diff)

Working version with signature and validation across a SOAP interface.

  • Property svn:executable set to *
Line 
1#!/usr/bin/env python
2
3"""WS-Security test server
4
5NERC Data Grid Project
6
7P J Kershaw 01/09/06
8
9Copyright (C) 2006 CCLRC & NERC
10
11This software may be distributed under the terms of the Q Public License,
12version 1.0 or later.
13"""
14
15reposID = '$Id$'
16
17import sys
18import socket
19
20# Web service interface
21from ZSI import *
22from ZSI.dispatch import SOAPRequestHandler, _client_binding
23from ZSI.auth import _auth_tc, AUTH, ClientBinding
24
25from BaseHTTPServer import HTTPServer
26
27from wsSecurity import *
28from wsInterface import *
29
30
31#_________________________________________________________________________
32def echo(ps):
33    """example service simply returns message sent to it"""
34   
35    import pdb;pdb.set_trace()
36    signatureHandler = SignatureHandler(\
37                            certFilePath='../../Junk-cert.pem',
38                            priKeyFilePath='../../Junk-key.pem',
39                            priKeyPwd=open('../../tmp2').read().strip())
40    signatureHandler.verify(ps)
41
42    request = ps.Parse(echoRequestWrapper)
43    response = echoResponseWrapper()   
44    response._message = request._message
45   
46    return response
47
48def _Dispatch(ps, modules, SendResponse, SendFault, docstyle=0,
49              nsdict={}, typesmodule=None, rpc=None, **kw):
50    '''Find a handler for the SOAP request in ps; search modules.
51    Call SendResponse or SendFault to send the reply back, appropriately.
52
53    Default Behavior -- Use "handler" method to parse request, and return
54       a self-describing request (w/typecode).
55
56    Other Behaviors:
57        docstyle -- Parse result into an XML typecode (DOM). Behavior, wrap result
58          in a body_root "Response" appended message.
59
60        rpc -- Specify RPC wrapper of result. Behavior, ignore body root (RPC Wrapper)
61           of request, parse all "parts" of message via individual typecodes.  Expect
62           response pyobj w/typecode to represent the entire message (w/RPC Wrapper),
63           else pyobj w/o typecode only represents "parts" of message.
64
65    '''
66    global _client_binding
67    try:
68        what = ps.body_root.localName
69
70        # See what modules have the element name.
71        if modules is None:
72            modules = ( sys.modules['__main__'], )
73
74        handlers = [ getattr(m, what) for m in modules if hasattr(m, what) ]
75        if len(handlers) == 0:
76            raise TypeError("Unknown method " + what)
77
78        # Of those modules, see who's callable.
79        handlers = [ h for h in handlers if callable(h) ]
80        if len(handlers) == 0:
81            raise TypeError("Unimplemented method " + what)
82        if len(handlers) > 1:
83            raise TypeError("Multiple implementations found: " + `handlers`)
84        handler = handlers[0]
85
86        _client_binding = ClientBinding(ps)
87        if docstyle:
88            result = handler(ps.body_root)
89            tc = TC.XML(aslist=1, pname=what + 'Response')
90        elif rpc is None:
91            # Not using typesmodule, expect
92            # result to carry typecode
93            result = handler(ps)
94            if hasattr(result, 'typecode') is False:
95                raise TypeError("Expecting typecode in result")
96            tc = result.typecode
97        else:
98            data = _child_elements(ps.body_root)
99            if len(data) == 0:
100                arg = []
101            else:
102                try:
103                    try:
104                        type = data[0].localName
105                        tc = getattr(typesmodule, type).typecode
106                    except Exception, e:
107                        tc = TC.Any()
108                    arg = [ tc.parse(e, ps) for e in data ]
109                except EvaluateException, e:
110                    SendFault(FaultFromZSIException(e), **kw)
111                    return
112            result = handler(*arg)
113            if hasattr(result, 'typecode'):
114                tc = result.typecode
115            else:
116                tc = TC.Any(aslist=1, pname=what + 'Response')
117                result = [ result ]
118
119               
120        sw = SoapWriter(nsdict=nsdict)
121       
122        sw.serialize(result, tc, rpc=rpc)
123               
124        signatureHandler = SignatureHandler(\
125                                certFilePath='../../Junk-cert.pem',
126                                priKeyFilePath='../../Junk-key.pem',
127                                priKeyPwd=open('../../tmp2').read().strip())
128        signatureHandler.sign(sw)
129       
130        return SendResponse(str(sw), **kw)
131   
132    except Exception, e:
133        # Something went wrong, send a fault.
134        return SendFault(FaultFromException(e, 0, sys.exc_info()[2]), **kw)
135
136#_____________________________________________________________________________
137class EchoSOAPRequestHandler(SOAPRequestHandler):
138    """Implement to allow overloaded do_POST in order to handle WS-Security
139    for outbound messages"""
140 
141    def do_POST(self):
142        """Override default to allow custom dispatch call"""
143        try:
144            ct = self.headers['content-type']
145            if ct.startswith('multipart/'):
146                cid = resolvers.MIMEResolver(ct, self.rfile)
147                xml = cid.GetSOAPPart()
148                ps = ParsedSoap(xml, resolver=cid.Resolve)
149            else:
150                length = int(self.headers['content-length'])
151                ps = ParsedSoap(self.rfile.read(length))
152        except ParseException, e:
153            self.send_fault(FaultFromZSIException(e))
154            return
155        except Exception, e:
156            # Faulted while processing; assume it's in the header.
157            self.send_fault(FaultFromException(e, 1, sys.exc_info()[2]))
158            return
159       
160        _Dispatch(ps, self.server.modules, self.send_xml, self.send_fault,
161                  docstyle=self.server.docstyle, nsdict=self.server.nsdict,
162                  typesmodule=self.server.typesmodule, rpc=self.server.rpc)
163
164
165#_____________________________________________________________________________
166def AsServer(port=80, 
167             modules=None, 
168             docstyle=0, 
169             nsdict={}, 
170             typesmodule=None,
171             rpc=None,
172             **kw):
173   
174    address = ('', port)
175    httpd = HTTPServer(address, EchoSOAPRequestHandler)
176    httpd.modules = modules
177    httpd.docstyle = docstyle
178    httpd.nsdict = nsdict
179    httpd.typesmodule = typesmodule
180    httpd.rpc = rpc
181    httpd.serve_forever()
182
183
184if __name__ == '__main__':
185    print "Server listening ..."
186
187    try:
188        AsServer(port=8080)
189
190    except KeyboardInterrupt:
191        sys.exit(0)
192
193    except socket.error, e:
194        print >>sys.stderr, "Server socket error: %s" % e[1]
195        sys.exit(1)
196
197#    except Exception, e:
198#        print >>sys.stderr, "Server: %s" % e
199#        sys.exit(1)
Note: See TracBrowser for help on using the repository browser.