[Twisted-web] secure access to xmlrpc, soap (access from ip-ranges,
login, ssl) - a feasible approach?
Marco Aschwanden
PPNTWIMBXFFC at spammotel.com
Thu Mar 9 12:20:04 CST 2006
Hi
I would like to write a server, that delivers the same services over
xmlrpc or soap. It is no problem to design this. The problem arises when
it comes to authentification.
What I want:
- Deliver services in xmlrpc or soap
- Deliver services only to people in well defined ip-ranges
(192.168.1.*,...)
- Deliver services only to logged in users (except for login requests
which should always pass!)
- User don't have to log in each time they do a request! (overhead would
be deadly)
- Deliver services encrypted (ssl) if desired
What I have:
- I have a server that delivers services over xmlrpc or soap
- I have a class that keeps track for users that have logged
in/expired/available.
- I have a class that can test, whether the request comes from a valid ip.
The problem(s):
- I know that twisted has "cred" library to authentificate people. I don't
see how this is usable with a stateless protocol like xmlrpc or soap. As
far as I understood the "cred"-library does not apply to xmlrpc or soap.
If it does, than a simple exmaple would be very nice.
To me it seems, that the best point to enforce "authentification" and
"logged sessions" is to override render-method of
--> twisted.web.xmlrpc.XMLRPC
--> twisted.soap.SOAPPublisher
from twisted.web.xmlrpc import XMLRPC
import xmlrpclib
import bsw_config
class XMLRPC_WITH_AUTH(XMLRPC):
def __init__(self):
XMLRPC.__init__(self)
def render(self, request):
"""Overriding this let me introduce authentification."""
# <Modification>
# --> verify whether the ip is in the allowed range -->
# I do it here, before any further handling is done!
# verify --> request.client.host is allowed
# </Modification>
request.content.seek(0, 0)
args, functionPath = xmlrpclib.loads(request.content.read())
# <Modification>
# Always let login request pass! (xxx Multicall?)
if not functionPath == u"do_login":
# verify user logged in already based on IP (port always
changes -
# because xmlrpc is stateless)
# what other possibilty do I have for a unique id?
if not verify_user_is_logged_in(request.client.host):
self._cbRender(Fault(xxx, xxx) , request)
return server.NOT_DONE_YET
# </Modification>
try:
function = self._getFunction(functionPath)
except Fault, f:
self._cbRender(f, request)
else:
request.setHeader("content-type", "text/xml")
defer.maybeDeferred(function, *args).addErrback(
self._ebRender
).addCallback(
self._cbRender, request
)
return server.NOT_DONE_YET
The two <modification></modification> show my intended interventions.
Is this a feasible approach?
The only unique id I have from the client is his IP - the socket/port, as
I said, changes with each request (stateless nature of xmlrpc/soap). This
poses a security risk, because clients served from the same
proxy/router/firewall have the same IP... which forces me to add a unique
token to each request (please not).
Do you know another unique item of each request, that identifies the
client further?
To further secure the transport, I would like to be able to transport the
data over ssl. Is this as easy as:
reactor.listenSSL(XMLRPC_PORT, server.Site(XmlrpcPublisher()), some_cert)
reactor.listenSSL(SOAP_PORT, server.Site(SoapPublisher()), some_cert)
Thanks for all your answers in advance,
Greetins,
Marco
More information about the Twisted-web
mailing list