Conversation
With this patch, developer could pass in a custom Event class through event_class argument to Server and Client in order to change the behavior of the default Event class.
Currently only two simple authentication methods are supported. Developer could implement other authentication methods by subclass existing middleware or create their own ones.
|
Hey glad to hear that you like zerorpc :) To confirm your last statement: yes it is preferable to keep auth outside of zerorpc for now. A middleware is perfectly fine. For the customization of the Event class, give me some time to review it. Thanks for contributing! |
|
Let's discuss the custom Event class patch here. I could send in another pull request when it's ready to be merged. |
|
Thanks for putting None everywhere, it reduces the number of files modified, and simply keep the new modifications as local as possible to Events. And I like that Core.py stays away from any strong knowledge about Events/Event. Btw that was a really dumb idea to name one class Events and the other one Event! We should definitively rename that. Lets rename Events into EventsTransport. That makes more sense. In term of design, I think that rather than providing en Event class to be used by the Events class. It would be better to provide an instance of a class replacing Events itself. This class could then provide its one Event class as well. Both customized Events and Event class should respect some well defined interface in order to work properly with zerorpc. It will allow people to customize even more what Events and Event are doing, so you could change the transport of zerorpc. Also, pay attention that there is one instance of Events per zerorpc Client or Server object, but Event can be recursively encapsulated! (this is not used by the official branch of zerorpc right now, but there is some experiments in the subcontext branch). I will try to look at this problem in detail during the weekend, especially how you implement the authentication, and see if I can come up with some satisfying ideas in order to solve your initial problem: adding auth to zerorpc. |
|
Thank you! I think the custom transport idea is great. Actually, I was trying to go that way. But I found it may bring some big changes to the current code base. And I wanted the patch to be less invasion as possible since people use zerorpc in production and such changes might break things. I'd love to contribute for the custom transport feature if you haven't started to do that yet. Just let me know. |
|
I did not started any implementation yet, and patches are welcome! I would like to talk about the different possible solutions first though. I was reading your code in detail in order to pinpoint what zerorpc is missing for your use case. I was considering extending the different uses of load_task_context/get_task_context that you already used to store your message signature, but I realized that it does not deserve the same purpose: A zerorpc.server, upon load_task_context() could load and verify the event header by raising an exception. But this is not the best logical place to put a check, and it becomes awkward when load_task_context() is used during a coroutine fork. Also, right now the client will not call load_task_context() when it receives messages from the server, since logically, you already know in which task you are, and so re-loading it would be redundant. The goal of load_task_context() and get_task_context() is initially to build a distributed tracer. For example, each time a new event is created, a trace_id is created or copied from the current task context. This permit passing the trace_id from a zerorpc.Server to another via zerorpc.Client. Your use case is different: you do not want to forward anything between services. You want to authenticate ALL the messages between a given zerorpc.Server and a zerorpc.Client. In order to do so, you want the Server and Client to inject a signature in every single event, that both side will verify against a given shared secret. But I am not teaching you anything here. The signature do not escape the boundaries of the Client/Server communication. The signatures are exchanged between a Server and a Client directly. By extension and to makes zerorpc implementation easier, we can assume that all the zerorpc.Client/Server attached to the same zerorpc.Context share the same secret (as you did in your proposal). Some people might prefer to have a different secret for every zerorpc.Client for example, without having to create a context for each of them. Feel free to share any idea if you think this problem should be solved. I see two direction were we could head in order to solve your problem:
Let me know what you think, and feel free to criticize and share any other idea. Thanks for reading up to this point ;) |
|
I/We'll have to look at this with the new middleware API I'm trying to finalize (I'm just committing it now, but it was actually a background work for the past few months). |
Conflicts: zerorpc/core.py
|
Great news! I've been busy with other work recently. Now I have some time working on zerorpc again. I'll port my authentication related code to 0.4 after I figure out how to play with the new middleware api nicely. |
|
I am not sure that you will be able to retrofit the current hooks to your
|
This reverts commit 10a1fe0. Conflicts: zerorpc/core.py zerorpc/events.py zerorpc/socket.py
|
I just pushed my authentication related code modified against the new middleware api and I managed to add all I want through middleware so I reverted my changes made to the core part of zerorpc. I found the latest middleware api brings much more possibilities. With the old version, I can't properly inject signature to the event to be sent because the old With the new version, the When it comes to authentication, there are many ways to do it. In my code, I demonstrated two simple ways. One is to use shared secret to sign the request and the other is oauth like request signing with client private key. Anyone with similar needs might find it useful. And one can easily add more authentication methods to meet their own needs. I need some advice on the way I used middleware to add authentication. If it's proper, I think we can consider this issue closed and just leave the Thanks a lot! |
|
I am really glad to hear that the new middleware api solved your problem!
|
|
Thank you! I'm looking forward to it. |
|
Don't really understand why this code isn't merged into the main repository. Having authentication is an important feature many users will want today, or will require tomorrow (after a security assessment of some type). The default should be to expose ZeroRPC without any authentication, but developers should be pulling from a third party repository to get authentication features. Also, having that important feature in a different repository will only bring problems: a change in this repository can break the authentication code, and nobody will notice it (unless there is some complex cross-project continuous integration setup). So, to sum up, I believe its best to merge making sure that this is disabled by default and is 100% back-compatible. |
|
The code hasn't been merged for a few reasons:
I hope you understand why it is not merged; but don't hesitate to ask questions if you need more details! Cheers, |
|
Additionally, zmq>=4 supports authentication. It exposes few different authentication method, all of that nicely integrated in zmq (so you get proper handshakes and so on). |
|
authentication support from zmq>=4 looks promising. I'm happy to rebase my code with the latest master when it comes out. I think maybe we could put middlewares like authentication and tracing in a contrib sub module just like what Django did for admin and flatpages. Users could enable these additional features by themselves and the zerorpc core keeps clean. |
|
Sounds good! |
I'm not quite sure if this patch should be merged. But I'd like to bring up a discussion about whether should zerorpc have authentication support built-in.
The need of authentication support start from day one when I use zerorpc to build some internal service since I have to expose this service to the internet.
When I heard the release of stack.io, I though I might use stack.io as a gateway doing the authentication work. But I couldn't find the authentication method for clients connected through zerorpc.
So I begin to add authentication support by myself.
This patch consists two commits. The first one patches current zerorpc code base to support custom Event class for Server and Client. And the second one add signed requests based authentication using custom Event class and proper middleware.
When I was modifying current zerorpc code base, I tried to change as less as possible and I put authentication related code in a separate file as kind of extension.
Here are some example code shows about how to use authentication:
I don't know the design decisions about authentication. If we decided not to include authentication in zerorpc, could we just merge the first commit and give the developers ability to change the default behavior of events so that they could implement their own authentication mechanism in their own code base?
Btw, I really enjoyed writing services with zerorpc. Thank you for this wonderful project.