EarthScope / ringserver

Apache License 2.0
30 stars 16 forks source link

auth for WRITE via websocket #17

Open crotwell opened 5 years ago

crotwell commented 5 years ago

Allowing WRITE via a websocket datalink connection is currently a bit dangerous when coupled with a proxy. For example, we have ringserver running on a machine that is not publicly accessible directly and use mod_proxy_wstunnel to allow outside clients to make the web socket connection. But this means that as far as ringserver is concerned, all connections come from the web servers IP address, and so the WriteIP configuration is useless as there is no way to separate which clients are allowed to write from those that are not.

For a traditional miniseed upload link this is not such a problem, as it will generally have opened firewall port with a direct socket connection and the IP based filtering is sufficient. But we are trying to use ringserver to allow certain users, for example, to send non-miniseed packets back in via datalink for a pick from a web based application.

Having the WRITE permission be based on an actual authentication system instead of simple IP based would address this, but would be significant effort I expect.

Possibly the best answer is to put authentication on the web server before mod_proxy_wstunnel forwards the connection, but I'm raising the issue as the websocket support in ringserver can make the effects of write permissions less obvious. In particular, opening WRITE access up to all of my local subnet is probably dangerous if that subnet includes a public web server with proxy_wstunnel enabled. Additionally, there is the problem that WriteIP applies to all listening ports. For a system that is intended to have one port for direct datalink uploads but also allow read only web socket access, the WriteIP applies to both of the ports. It might be nice to be able to configure the WriteIP directive apply only to say the direct DataLinkPort but not apply to a ListenPort HTTP.

crotwell commented 5 years ago

Did some more reading and it is not clear to me if apache can do the auth before proxying the web socket. A token based system would be nice and I think is the way this type of thing tends to be done. For example I have used https://jwt.io/ on the javascript side in the past and then maybe there is a C library for RFC 7519 on the ringserver side???

Perhaps https://github.com/benmcollins/libjwt

chad-earthscope commented 5 years ago

but would be significant effort I expect.

Indeed. For this reason, and that it's usage is esoteric, it's not something I plan on looking into much.

Possibly the best answer is to put authentication on the web server before mod_proxy_wstunnel forwards the connection

This would be a good way to do it. Either have a front-end doing tokens or other for of auth and letting ringserver run in the background. Writes could write to the authentication proxy, read-only-ers could talk directly to the ringserver?

Additionally, there is the problem that WriteIP applies to all listening ports

Yeah, that would allow a simpler version of the setup below where different ports, as opposed to different paths, are used.

crotwell commented 5 years ago

Yep, I agree auth is too big a beast to injest into ringserver. But the separation of WriteIP by port is probably important. Even worse case than mine would be having the web server and ringserver running on the same machine with mod_proxy_wstunnel enabled. The WRITE on the websocket might then appear to come from localhost and so be enabled by default?

Perhaps the default configuration should disable WRITE for all websocket connections?

chad-earthscope commented 5 years ago

Perhaps the default configuration should disable WRITE for all websocket connections?

That's a bit too targeted IMHO.

I think an approach where WRITE can be limited to certain ports allows a broad set of combinations while being explicit from a config perspective, and tractable in code.

crotwell commented 5 years ago

OK, but doesn't there also need to be some way to disable WRITE from localhost, currently enabled by default? Otherwise a proxy_wstunnel is always allowed to write?

chad-earthscope commented 5 years ago

OK, but doesn't there also need to be some way to disable WRITE from localhost, currently enabled by default? Otherwise a proxy_wstunnel is always allowed to write?

Documented as: "If no client addresses are granted write permission via WriteIP then the address 127.0.0.1 (local loopback) is granted write permission." Perhaps it's not clear enough, but that also means that if any WriteIP is specified localhost is not given right permission, i.e. it's only a default when nothing is specifically allowed to write.

crotwell commented 5 years ago

Right, but if I have ListenPort 6383 HTTP DataLinkPort 15003 with no WriteIP lines, and I want write access to 15003, but only from localhost then this appears to work, but also opens access via the proxy_wstunnel web socket that is not obvious. And if I understand what you are saying, to disable write to the websocket using the new port limited system, I would have to specifically enable write from localhost to 15003, even though it is enabled by default? Seems convoluted.

All I am saying is that write via datalink or seedlink should be fine to default to ok from localhost, but perhaps "listenport http" should default to not even localhost given the greater probability for it to be proxied locally?

chad-earthscope commented 5 years ago

but perhaps "listenport http" should default to not even localhost given the greater probability for it to be proxied locally?

That, i.e. special/different default rules for HTTP, is just-as and even more convoluted in my opinion. It certainly is more complexity in the code.

I think if an operator is at the technical level of setting up ringserver that is expected to handle WRITEs via WebSocket and using a localhost proxy to offload the authentication, understanding and adding an explicit WriteIP declaration is not a big ask.