ZSI + pyopenssl
Verfasst: Donnerstag 31. Januar 2008, 14:22
Hier hab ich ja schonmal ein kleines funktionstuechtiges Beispiel einer Socketverbindung mit pyopenssl gepostet. Wie man Pythons HTTPServer damit verheiraten kann, habe ich in diesem Rezept gefunden, das funktioniert auch super. Nun wollte ich gerne ZSI mit pyopenssl kombinieren (ich muss dazu sagen, dass ich von ZSI und Soap nicht so viel Ahnung habe...).
Um einen Service zu dispatchen, kann man den ServiceContainer verwenden. Da der auch nur von dem HTTPServer abgeleitet ist, hab gedacht, dass ich jetzt genauso wie in dem Rezept vorgehen kann:
Der Server versteht auch ein ganz normales GET, und da laeuft auch alles wie erwartet. Da ich noch nicht genau weiss, wie ich den SSL-Kram bei ZSI Client-seitig handhabe, hab ich mir zum Testen meines Webservices erstmal zwei Clients manuell gebastelt, einmal mit SSL und einmal zum vergleich ohne SSL. Es funktioniert ebenfalls wie erwartet, mit dem SSL-Client genau dann, wenn die Zertifikate auf beiden seiten richtig gesetzt sind, mit dem anderen Client gar nicht.
Was ich jetzt nicht verstehe: Nehme ich meinen ganz normalen ZSI-Client-Proxy, funktioniert die Verbinung und ich bekomme das Ergebnis meines Services-Calls zurueck:
Warum? Ich wuerde jetzt erwarten, dass der Server die Verbindung ablehnt, da er ja ueberhaupt keine Zertifikate/Authentifizierung vom Client bekommt... Ich sehe ja auch, dass die callback-Funktion gar nicht aufgerufen wird, da sie keine Ausgabe produziert.
Naechste Frage ware dann, wie ich mit ZSI einen SSL-Client hinbekomme, denn mir geht es vor allem um den Client, nicht um den Server...
Hier sind die restlichen Dateien, die fuer ein lauffaehiges Beispiel benoetigt werden (ist das Standard-Beispiel mit dem Mathe-Service, den man in einigen Tutorails findet):
MatheService.wsdl
MatheService_services.py
MatheService_services_server.py
MatheService_services_types.py
Um einen Service zu dispatchen, kann man den ServiceContainer verwenden. Da der auch nur von dem HTTPServer abgeleitet ist, hab gedacht, dass ich jetzt genauso wie in dem Rezept vorgehen kann:
Code: Alles auswählen
#!/usr/bin/env python
import os, socket
from ZSI.ServiceContainer import ServiceContainer, SOAPRequestHandler
from MatheService_services_server import SquareService
from OpenSSL import SSL, crypto
from BaseHTTPServer import HTTPServer
class SecureServiceContainer(ServiceContainer):
def __init__(self, server_address, services=[],
RequestHandlerClass=SOAPRequestHandler):
ServiceContainer.__init__(self, server_address, services,
RequestHandlerClass)
keystore = crypto.load_pkcs12(open("serverkey.p12").read(),
"geheim")
ctx = SSL.Context(SSL.SSLv23_METHOD)
ctx.set_verify(SSL.VERIFY_PEER, self.verify_cb)
ctx.use_privatekey(keystore.get_privatekey())
ctx.use_certificate(keystore.get_certificate())
ctx.load_verify_locations("ca-certs.pem")
self.socket = SSL.Connection(ctx, socket.socket(self.address_family,
self.socket_type))
self.server_bind()
self.server_activate()
def verify_cb(self, conn, cert, errnum, depth, ok):
print "Got certificate: %s" % cert.get_subject()
print "Issued by: %s" % cert.get_issuer()
return ok
class SecureSoapRequestHandler(SOAPRequestHandler):
def setup(self):
self.connection = self.request
self.rfile = socket._fileobject(self.request, "rb", self.rbufsize)
self.wfile = socket._fileobject(self.request, "wb", self.wbufsize)
def do_GET(self):
self.send_xml(SquareService._wsdl)
service_container = SecureServiceContainer(("127.0.0.1", 8080),
RequestHandlerClass=SecureSoapRequestHandler)
for service in (SquareService(), ):
path = service.getPost()
service_container.setNode(service, path)
service_container.serve_forever()
Was ich jetzt nicht verstehe: Nehme ich meinen ganz normalen ZSI-Client-Proxy, funktioniert die Verbinung und ich bekomme das Ergebnis meines Services-Calls zurueck:
Code: Alles auswählen
#!/usr/bin/env python
from MatheService_services import *
import sys
loc = SquareServiceLocator()
proxy = loc.getSquarePortType(tracefile=sys.stdout)
request = getSquareRequest()
request._request = 2.0
response = proxy.getSquare(request)
print ">>>", response._response
Naechste Frage ware dann, wie ich mit ZSI einen SSL-Client hinbekomme, denn mir geht es vor allem um den Client, nicht um den Server...
Hier sind die restlichen Dateien, die fuer ein lauffaehiges Beispiel benoetigt werden (ist das Standard-Beispiel mit dem Mathe-Service, den man in einigen Tutorails findet):
MatheService.wsdl
MatheService_services.py
MatheService_services_server.py
MatheService_services_types.py