-
Notifications
You must be signed in to change notification settings - Fork 155
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Proxy JMAP requests in a Murder #3564
Conversation
d529754
to
136ecd6
Compare
I think this is finally done (other than Cass test). It properly proxys JMAP requests and JMAP/WS connections over both HTTP/1.1 and HTTP/2. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know the bigger picture well enough to spot potential abstraction problems, but taken line by line it seems okay except for a couple of possible edge cases
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks sane to me, but bear in mind that I haven't grokked all of the murder code, yet. I'd like to approve when we see a Cassandane test working.
I can confirm that my local build does not yield any compiler errors. However, the whole current Cassandane Murder test suite fails with valgrind errors.
I've looked into adding a JMAP Murder test to Cass and it looks non-trivial. I might need some help in getting the infrastructure built, mainly getting a second httpd instance running. |
6712eca
to
fda7e7e
Compare
Do you have a working local setup? If so, can you send me your imapd.conf files from the frontend, backend, and mupdate server? (If the frontend and mupdate server are the same server, that's actually great, because that's the setup Cassandane uses.) I figured out the long way how to get it working for IMAP back when I wrote the Murder suite, but I'm not sure what the config needs to look like to have it proxy HTTP as well -- but I know the infrastructure fairly well, so once I know what the config needs to look like I think I can make Cassandane do it. |
I have frontend and mupdate as the same server. Other than that, its the same setup as IMAP in a Murder, with httpd on frontend and backend (with JMAP module enabled) |
The trouble is, I don't understand the IMAP murder config quite well enough to know how to generalise it, I just know what I needed to do to wrestle it into working 😅 So it'd really help to see examples of working HTTP, cause e.g. I'm not sure where I'll need to configure the port numbers? Though I suppose you might be using port 80/443 by default and not actually have port numbers explicitly configured, whereas Cassandane needs to sticks everything on :910x. Hmm. |
Fair enough. I will cobble together a minimal config for you |
Great, thanks! |
Actually, do any of the tests in Murder.pm actually proxy a client request from the frontend to the backend? They all appear to talk to a frontend or backend directly. |
0dcc55e
to
4c10d24
Compare
No idea really. The ones that talk to the frontend expect the frontend to do whatever it needs to do to service the request. If none of them exercise anything that needs to be proxied, then we need to add some tests for things that do get proxied. I might be misunderstanding how murder proxying works. I wrote these tests mostly in the dark, so I don't expect them to be either correct or thorough as they are. They're better than the nothing we previously had, but they still need a lot more work. |
4c10d24
to
300cc2a
Compare
@elliefm So, I took a look at the Cass Murder config and I think we can use the "include port in servername" trick for JMAP, but this trick can only work for one protocol at a time. So, we wouldn't be able to have an IMAP service run on the backend, just HTTP. This is because any service running on the proxy (IMAP, JMAP, POP) will try to connect to the port encoded in servername. |
Ahh interesting. So I think, then, that instead of having just |
This sounds like a reasonable plan to me. |
300cc2a
to
53d1422
Compare
@ksmurchison A first stab at what we've discussed about testing this is in cyrusimap/cassandane#151 |
53d1422
to
744352b
Compare
… to timeout first (so close frame gets proxied)
…connection (which includes struct protgroup) and properly handle backend timeouts for pipes
744352b
to
c9eec8f
Compare
@ksmurchison What behaviour would you expect to see when making a request directly against a backend that does not have that user's account on it? I have three tests so far:
At the moment I get an "internal server error" from backend2, and I'm not sure if this is the correct thing to expect, or if something is awry. I think I would expect some kind of "mailbox does not exist" or "access denied", or something along those lines, not "internal server error". But it's worth keeping in mind that the sasl replacement Cassandane uses returns "OK" for any user unless the username is the string "bad", so we're in a maybe slightly unusual situation where a user can successfully authenticate to a backend that their account is not on -- and maybe that's why it's winding up in an internal server error situation instead. What do you think? Here's the full transaction:
|
Ahh, syslog reveals where that error comes from:
|
If I take "caldav" and "carddav" out of httpmodules (leaving just "jmap"), then jmap direct to backend2 responds 404 not found, which makes sense. So I guess maybe we've newly discovered a murder bug in the calendar autoprovisioning, but that's not related to this PR. |
I think I'm happy with this, based on my WIP tests. It successfully proxies a simple JMAP request when it's supposed to, and doesn't proxy it when it's not supposed to. I think/assume the JMAP implementation is fairly consistent, such that if one JMAP command proxies correctly they all should -- but if there's any that are known to be weird and we should test specifically, please let me know! @rsto You also mentioned wanting to see a Cassandane test for this -- are the tests in cyrusimap/cassandane#151 enough to satisfy you that this PR works? (Half of that PR is infrastructure changes; the interesting tests are Murder.jmap_frontend_commands, Murder.jmap_backend1_commands, and Murder.jmap_backend2_commands) I'm leaving the Cassandane tests PR as a draft for now because I have more work/refactoring I want to do on the infrastructure part. |
Hmm. Running Since the source for the build I'm testing doesn't exist anywhere as its own entity, the line numbers quoted below might not correspond with line numbers in your local files. So you'll probably wanna run this yourself to get real line numbers...
Looks like the thing that's being leaked is a Though, I've just noticed that
So we're actually in the process of shutting down when we allocate this new prot_waitevent that then gets leaked? That's weird. It's also weird that I don't see that "Shutdown file: ..., closing connection" log line anywhere. There is a "Received bad client magic byte string, closing connection" from the backend1 httpd, and an "end of file reached, closing connection" from the frontend httpd. For what it's worth it's the frontend httpd that the leak is being reported in. I'm really confused by the valgrind backtrace telling me we came from the "Shutdown file:" block, but that log line not appearing in syslog. So I don't trust the report, but I don't know how to proceed further. |
Oh, I changed branch while briefly distracted with something else and forgot to change back, so disregard everything I said about being in a shut down, I had the wrong line numbers myself! 😅
|
[edit from elliefm: There's tests for this in cyrusimap/cassandane/pull/151]