Skip to content
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

spike: Investigate Web Service Workers #21593

Open
allisonkarlitskaya opened this issue Feb 6, 2025 · 1 comment
Open

spike: Investigate Web Service Workers #21593

allisonkarlitskaya opened this issue Feb 6, 2025 · 1 comment

Comments

@allisonkarlitskaya
Copy link
Member

allisonkarlitskaya commented Feb 6, 2025

These are notes for https://issues.redhat.com/browse/COCKPIT-1240

This is a spike to investigate replacing much of cockpit-ws with a web service worker running in the user's browser.

After an initial round of research this seems increasingly desirable. The thing stopping me before is the perception of an extremely limited context in which service workers seemed to be available (HTTPS only, no self-signed certs, no private mode in Firefox) but I've convinced myself that the web community views service workers as a first-class technology that is only going to grow in use going forward.

In particular, on the Firefox front, service workers not working in private browsing is not a design decisions, but a bug caused by an implementation limitation, and Mozilla is actively working on it: https://bugzilla.mozilla.org/show_bug.cgi?id=1320796

One potential remaining negative is that service workers can't currently work with sandboxed iframes whatwg/html#10585. That's something we don't currently do, but might want to. Service workers would give us new tools to permit multiple separate logged-in sessions, though.

Another issue: web service workers only work in "secure contexts" which I think excludes self-signed certificates. This needs to be investigated more, but if we end up banning self-signed certificates, I don't think it would be a bad thing. Our users could (and should!) install a CA via their browser or OS settings and this would work. Having the browser "INSECURE! Are you sure!!" page waved by just before entering your root password is definitely already bogus. As a bonus, not worrying about self-generated certificates in Cockpit would allow us to substantially simplify our service startup (eliminating all the stuff around the certificate helper, etc).

We can use service workers to intercept "fetch" style requests (ie: for html, css, js, etc. resources) but not for websocket/webtransport traffic. That's ok: we can pass messages to the service worker and can receive responses which means we can continue to use a mechanism like the ParentWebSocket approach already in use in Cockpit for communicating with the shell: https://github.com/cockpit-project/cockpit/blob/26af34d570a18d8868c254724abc8d733fafad56/pkg/lib/cockpit/_internal/parentwebsocket.ts

If we have a web service worker in the browser we could also consider connecting to servers by using SSH. Web browsers can't connect directly to SSH from JS (raw socket traffic would be too big of a violation of the sandbox) but there are various dumb wrappers that are essentially SOCKS proxies via websocket that we could run on bastion hosts. But, careful: if we do SSH in the browser, then this changes the character of a bastion host into something that essentially allows unfettered access to the SSH port on all machines behind the firewall (or maybe even other ports). Previously the bastion host contained the SSH client and would only allow arbitrary data to be sent inside of the session of an already-authed connection. Moving SSH to the browser means handing a pre-auth socket connection to the open internet. Maybe we don't want that. But: if the browser does SSH for itself then we get an end-to-end secure connection from the browser to the target server without the bastion host being able to MITM the connection.

Otherwise the plan is to connect to the webserver using HTTP/3 WebTransport:

Using HTTP/3 has its own set of interesting challenges and is semi-orthogonal to using service workers. To keep things reasonable for the time being the plan would be to proceed with this spike by taking an existing cockpit-ws implementation (probably the test server replacement from #20706) and speak to it using websockets. That already gives us a connect to a running bridge which we could use to build out the necessary cockpit-ws parts that would live in the browser. Once that task was complete we could look into implementing a WebTransport-based backend as a next task.

The overall approach here would be to have a webserver which:

  • serves /worker.js or whatever, if the Service-Worker header is set
  • serves /*.html as a simple page that attempts to install the service worker:
    • reloding itself (via the worker) if that's successful
    • showing a "browser not supported" page otherwise
  • a websocket connected to the bridge (± auth)

This will probably turn into a trivial to small amount of extra Python work (on top of the existing test server) plus an extremely large amount of .js work. I think I'd like to tackle this in TypeScript because it's already well past the size limit at which .js becomes difficult to maintain and I anticipate several reactors along the way.

A good final architecture might involve serving the static files (the service worker itself, plus the redirect pages) via HTTP/2 or HTTP/1.1 via TCP and using HTTP/3 only for the WebTransport. This would simplify the implementation of a security-critical component. It also means that we can use any HTTP implementation that's convenient for us without having to worry about HTTP/3 support (since this will likely look like some very very custom code anyway).

@martinpitt
Copy link
Member

martinpitt commented Feb 6, 2025

Thanks @allisonkarlitskaya for your investigations!

web service workers only work in "secure contexts" which I think excludes self-signed certificates

I'm afraid you are right, e. g. the w3c spec stackoverflow, and a random developer blog all agree on this.

To be honest, this is a showstopper for me, unless browsers respect the "accept this certificate anyway" user decision. We can't just break all these existing installations out there on install, and even for many use cases it is totally impractical or unnecessary to set up a "proper" TLS certificate. This is probably the hardest problem of the internet still sadly -- e.g. most people use the TOFU (trust on first use) approach with SSH, which is effectively what we currently do with the [ Yes, trust this certificate ] button. Remember how many people were running into that Safari bug, and that wasn't even Linux/Windows users (which are much more numerous for our use case).

To be honest, this leaves me a bit disappointed -- it's not like with service workers you can do fundamentally more things, i.e. if TOFU is good enough for a normal web site, it should be good enough for a service worker enabled web site. But 🤷

So if we consider that, before we sink time into the actual implementation, we need to address the "wean cockpit off self-signed certs" problem first. Discuss this with RHEL product managers and customer account managers, with the Fedora server group, and see what we can do there. I know that this most probably isn't the work you signed up for, and I'm not asking you to do it -- I'm just asking you to not sink too much time into this yet.

Of course, spending a few days on a demo is fine, then we can justify this better. But nothing fancy like talking to a real ws, Typescript and anything.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants