[Twisted-Python] Any examples of an authenticating XMLRPC server?
I'd like to add a number of XMLRPC services to an existing Nevow site that's both SSL encrypted and Guarded. However, when I take the straightforward tack of adding an XMLRPC instance to my site as /RPC , the client is unable to connect. It appears as though the client (Python's xmlrpclib) can't negotiate a login with the Nevow guard. Reading Andre Dalke's post (and the subsequent replies): http://twistedmatrix.com/pipermail/twisted-python/2003-June/004447.html it seems as though a rewrite of cred about a year and a half ago should have made it possible to use cred for doing the authentication required for both form-based and HTTP-AUTH-based queries (such as xmlrpclib uses). However, I'm not sure how all of that would interact with the Guard mechanisms (e.g. creating sessions, redirecting between forms, and the like). Anyway, I'm wondering if anyone has any code that does this, or information about the current state-of-the-art. Enjoy yourselves, Mike ________________________________________________ Mike C. Fletcher Designer, VR Plumber, Coder http://www.vrplumber.com http://blog.vrplumber.com PyCon is coming...
Mike C. Fletcher wrote:
I'd like to add a number of XMLRPC services to an existing Nevow site that's both SSL encrypted and Guarded. ....
... I'm wondering if anyone has any code that does this, or information about the current state-of-the-art.
I have an example from my project that does (I think) what you want. It's not the best code -- exarkun made some suggestions at PyCon last year on how to clean up the structure, and I'm embarrassed to admit I haven't yet implemented his suggestions (hey, it works ;). I'll send the files to you off-list because I don't want to clutter up the list, but if anyone else is interested I'll be happy to share them (or send them to the list if one of the twisted gurus thinks its worthwhile). Cheers, Steve
Hey Jordan and Andy, Attached are the modules of my app that handle XMLRPC and web basic auth over SSL. Note that there's no nevow here, but the same auth facility is used for both a simple static web interface and the XMLRPC service. You can see some vestigial (and inactive) PB stubs, which await time and my grokking Brian's new PB stuff. (Anyway I hadn't yet extended pgercred to support PB ... an exercise for the reader ... and if any readers want to hack on that, I'd love to see it ... that would make things much more interesting! :) Jp's advice, which has since faded into the dark backward and abysm of my head, had to do with some refactoring of pgercred ... hey jp, maybe you could remind me, if you have a chance to peek at it again! The pgertap, pgerxmlrpc, and pgercred modules are server-side and xmlrpcinterface is a client module. They are not runnable without some more stuff from the app (see below), and I haven't taken the time to create a self-contained runnable example along these lines, but I think it wouldn't be too hard, and IMO a nice addition to twisted's examples. Acknowledgement: the code that does the work in pgercred is based on an example that Moshe did a while back (I don't remember exactly what I copied, but I think the main thing was most or all of the BasicAuthResource class). The "engine" that gets passed to pgerxmlrpc is the guy that handles the application logic (he sits above an adbapi layer and other assorted back-end stuff). I didn't include that module because it's not relevant to this thread, but if anyone is curious, I put a tarball of the app at: http://ned.gsfc.nasa.gov/PanGalactic.tar.gz Caveats: it contains some horriblenesses, not much doc, and I haven't released it "publicly" yet. We used to have anonymous access set up for CVS on ned (remember, radix? ;), but NASA/GSFC has tightened up its firewalls considerably since then ... rats! :( Critiques or razberries welcomed, as long as they're constructive razberries! :) Cheers, Steve
On Sun, 2005-02-27 at 03:46 -0500, Stephen Waterbury wrote: [snip everything for brevity] Thanks for sharing this Stephen. It's made me question the realm-portal architecture I've been using. I notice that Stephen creates multiple realms - one for each "service" your application provides. Each realm then has a portal to connect it to the checker(s). That is interesting because the approach I have taken is to have *one* realm for the entire application and a portal for each "service". For instance I might have a single instance of my.app.Realm and one each of my.web.public.Portal, my.web.admin.Portal, my.web.xmlrpc.Portal, my.ftp.Portal etc. The reason I structure my code like this is because I consider the realm to be the "hub" of the application (something I thought the cred HOWTO was hinting at). My realm generally has all sorts of useful attributes, i.e. a ConnectionPool, as well as the application's "global" API. I also anticipated that, one day, my realm instance would need to be more aware of the avatars it had created. Right now, the only issue I have with my singleton realm way of working is that the realm's requestAvatar can get big and tends to look like a switch statement. It has to know about everything going on, even if it doesn't much care about the avatar once the method returns. Stephen's approach, by comparison, seems a little simpler in this respect in that each realm is there to create an particular type of "service" avatar. I still think that one realm and multiple portals is a better model but does anyone anyone else have opinions, suggestions, hints etc. Thanks, Matt -- __ / \__ Matt Goodall, Pollenation Internet Ltd \__/ \ w: http://www.pollenation.net __/ \__/ e: matt@pollenation.net / \__/ \ t: +44 (0)113 2252500 \__/ \__/ / \ Any views expressed are my own and do not necessarily \__/ reflect the views of my employer.
On Mon, 2005-02-28 at 14:50 +0000, Matt Goodall wrote:
Right now, the only issue I have with my singleton realm way of working is that the realm's requestAvatar can get big and tends to look like a switch statement.
If there's an underlying avatar, you can adapt it to the interface requested by the portal. If there are multiple avatar sources, i.e. different interfaces get totally different "users", multiple realms may be better (and you could put the shared logic in an object they all refer to).
Stephen Waterbury wrote: ...
Critiques or razberries welcomed, as long as they're constructive razberries! :)
This is extremely illuminating. The key approach/idea that I was missing is this: You can create a root web.resource.Resource() and add a child "" that handles all URLs not otherwise matched by a known child. This "" child handles the common web-browser case, basically anything not going to your "special" directories. This child is the protected Nevow portal that we all know and love; on attempting to walk into it all the Nevow machinery should trigger. Now you register your Basic-Auth-protected XMLRPC/SOAP portals as parallel children of the Nevow portal, "RPC" and "SOAP". These are again, portals, so they do their own credential checking, thus don't *necessarily* have to use the same cred mechanism, but can if they want to. This doesn't actually do what I was *trying* to do, which was to make it possible to log into the main site using Basic auth *or* the Nevow web forms, but it handles what we actually need to do perfectly, so I can just stop trying to do what I was trying to do :) . I'm about to sit down to implement this approach for our system. Much obliged, Mike ________________________________________________ Mike C. Fletcher Designer, VR Plumber, Coder http://www.vrplumber.com http://blog.vrplumber.com PyCon is coming...
On Mon, 2005-02-28 at 14:15 -0500, Mike C. Fletcher wrote:
Stephen Waterbury wrote: ...
Critiques or razberries welcomed, as long as they're constructive razberries! :)
This is extremely illuminating. The key approach/idea that I was missing is this:
You can create a root web.resource.Resource() and add a child "" that handles all URLs not otherwise matched by a known child.
This is incorrect. A child of "" matches the empty path segment. Most of the time this is used to handle a URL that ends in a "/" but an empty segment is also legitimate in the middle of a URL. For instance, the URL "/foo/bar/" translates to segments of ("foo", "bar", ""); "/" translates to ("",); "/foo//bar" translates to ("foo", "", "bar"). In Nevow, you handle unmatched children by overriding locateChild(self, ctx, segments) or, in the case of a rend.Page subclass, providing a childFactory(self, ctx, name) method. - Matt
This "" child handles the common web-browser case, basically anything not going to your "special" directories. This child is the protected Nevow portal that we all know and love; on attempting to walk into it all the Nevow machinery should trigger.
Now you register your Basic-Auth-protected XMLRPC/SOAP portals as parallel children of the Nevow portal, "RPC" and "SOAP". These are again, portals, so they do their own credential checking, thus don't *necessarily* have to use the same cred mechanism, but can if they want to.
This doesn't actually do what I was *trying* to do, which was to make it possible to log into the main site using Basic auth *or* the Nevow web forms, but it handles what we actually need to do perfectly, so I can just stop trying to do what I was trying to do :) . I'm about to sit down to implement this approach for our system.
Much obliged, Mike
________________________________________________ Mike C. Fletcher Designer, VR Plumber, Coder http://www.vrplumber.com http://blog.vrplumber.com PyCon is coming...
_______________________________________________ Twisted-Python mailing list Twisted-Python@twistedmatrix.com http://twistedmatrix.com/cgi-bin/mailman/listinfo/twisted-python
Matt Goodall wrote:
On Mon, 2005-02-28 at 14:15 -0500, Mike C. Fletcher wrote:
Stephen Waterbury wrote: ...
Critiques or razberries welcomed, as long as they're constructive razberries! :)
This is extremely illuminating. The key approach/idea that I was missing is this:
You can create a root web.resource.Resource() and add a child "" that handles all URLs not otherwise matched by a known child.
This is incorrect. A child of "" matches the empty path segment. Most of the time this is used to handle a URL that ends in a "/" but an empty segment is also legitimate in the middle of a URL.
I stand corrected, though somewhat confused as to how Stephen's code is working, then. My own experience does back up your statement, though.
In Nevow, you handle unmatched children by overriding locateChild(self, ctx, segments) or, in the case of a rend.Page subclass, providing a childFactory(self, ctx, name) method.
Indeed, as I discovered in implementing this. Still, Stephen's approach works fine, I was just wrong about thinking it was implemented automatically for the "" case. To make it work with a Nevow site, I created a root resource like this: class SiteRoot( object ): __implements__ = (inevow.IResource, ) isLeaf = False def __init__( self, root ): """Initialise the overall root""" self.root = root self.RPC = webservices.XMLRPCServer() def locateChild(self, ctx, segments): """Locate child, return as inevow.IResource""" if segments: if segments[0] == 'RPC': return self.RPC, segments[1:] return self.root, segments def renderHTTP( self, ctx, **named ): """Render this resource on an HTTP request""" raise ValueError( """You shouldn't be able to view this node!""" ) then wrap the SiteRoot instance in a nevow.appserver.NevowSite instance (it won't work if you try to use a twisted.web site, because that site class doesn't know how to traverse Nevow resources). You also AFAICS should not wrap the "root" in an appserver.NevowSite instance (it seems there should only be one site instance for any given web-server). So, to recap: nevow.appserver.NevowSite SiteRoot( root ) root = guard.SessionWrapper( portal.Portal( realm.YourRealm( rootResourceForNormalSite ) ) ) -- with the appropriate credential checkers registered. Enjoy, and thanks all, Mike ________________________________________________ Mike C. Fletcher Designer, VR Plumber, Coder http://www.vrplumber.com http://blog.vrplumber.com PyCon is coming...
participants (4)
-
Itamar Shtull-Trauring
-
Matt Goodall
-
Mike C. Fletcher
-
Stephen Waterbury