Consolidating The Console

Just a small comment regarding #1 - @TimoGoebel did some initial work on jwt as well in https://github.com/theforeman/foreman/pull/5596 as part of an effort to introduce GraphQL, so it would be a good idea to look into that as well and see that we don’t have duplicate effort/implementations.

1 Like

Hey @tbrisker, thank you for bringing this to my attention. I don’t think it really conflicts here, au contraire, I think seeing an initial implementation might help the cause :slight_smile: Either way, if you ask me, I’ll sign a JWT, containing hostname and port retrieved from compute resource, using foreman’s private key as this is readily available. The validation on proxy side is then to be done by its public key.

Meanwhile I’ve pushed a PR for websockify (including unit tests), so, we’re closing in on point 1:
https://github.com/novnc/websockify/pull/372

Do you mean pushing an update to EPEL? This can be a bit issue since upstream hasn’t done an update for three years (0.8.0 is the latest, also in EPEL). The code is a quite change for patch carried in EPEL (new deps), let’s see. The best thing is to ask upstream to do a release, then ask CentOS packagers to do the same. But remember, the EPEL policy is no major changes, only bugfixes :frowning: Let’s figure it out, we can always carry new version in our repos.

1 Like

Allright, another year, another update :stuck_out_tongue:

So, the PR for getting JWT token in Websockify has been merged.
https://github.com/novnc/websockify/pull/372

This is a big step forward as we’ll now able to move to the next steps:

  • Running this on the Smart-Proxy
  • Expose this console-proxying capability
  • Share the right secrets → I think this is our new problem-child; so input would be very welcome here, let me explain:
  • Still would need to proxy the websocket to the correct smart-proxy, I’m thinking “https://foreman-server/console-proxy//” which can be configured in the webserver to proxy this to a different backend

The JWT implementation for Websockify is enhanced in order to support JWE as well, in “layman terms” this means that we encrypt the content of the JWT using the public key of the receiver and Sign it using the Private key of the sender.

I think it would be valuable for us to implement the feature using JWE instead of simple JWS; however, the big question here is: how would I share the public keys of each end?

  • I think it’s easy to create an API extension point for the “Console-Proxy” feature, which can return the public key, but would it be wise?
  • Even more, would it be wise to also enhance this API and allow passing a public key from the sender (being The Foreman Server) to the proxy?
    • What would be the trigger to send this?
    • Or do I enhance the foreman API to send a public key on a proxy’s request?

Do we already have an infrastructure for passing public keys? Or, how would you guys do this?

Kind regards,
Arend

2 Likes

Can you explain why? Everytime I can use symetric cryptography instead of asymetric, I go for it. It’s more simple.

I might not understand the whole picture at the moment, but can’t we simply deploy (public) key(s) using our installer? This is something that does not change. For symetric that would be just a string which we can generate randomly and store in answers file and deploy where necessary.

Hi! Thanks for your response! Actually JWE allows for the usage of symetric keys as well; as you state it would greatly simplify the deployment.

  • Would it be okay that this is passed as an (foreman-proxy) installation argument? e.g. console-symetric-key?
  • Or would we trust the Foreman API for passing the console symetric key (as, by my assumption, this has TLS by default and can be deemed secure?)
  • Or would we trust the Proxy API instead? (also, this seems to be secure and only allows the foreman to access this; would make it possible to use different symmetric keys for different smart-proxies :slight_smile:

I would vote for the last case? Unless my assumptions on using TLS are greatly exaggerated?
Would also be fairly easy to implement :slight_smile:

At this moment I’d avoid building this support into the smart-proxy. Currently Foreman talks directly to compute resources and is the only one guaranteed to have a routable connection to them. Proxies may not and have no knowledge of compute resources at all (whether this is correct or not is another question). Other than that the clients are also not guaranteed to have connection to smart proxies. That means you’ll always need a console proxy on the Foreman server itself. In a schema:

client.example.com <-> foreman.example.com <-> compute.example.com

In the future this may add indirection via a smart proxy (which IMHO does make sense) but you’ll still have a proxy on foreman.example.com.

This will simplify your design.

Currently the Foreman user launches the websockify daemon with certs. This means the Foreman user needs permissions I’d like to get rid of. Could we run the websockify daemon (unencrypted) on localhost and use the webserver (Apache/Nginx) as a reverse proxy? We would need to think about the development setup, but a setting to override the host/port is probably sufficient.

Will this work in a load balanced setup?

If every server runs it on localhost and the webserver also proxies to localhost I don’t see why it wouldn’t. As long as the load balancer keeps the TCP session to one backend. It also means the webservers need to use a shared certificate to encrypt the data to send to the client so any backend can validate it.

@UXabre it’s been a while. Do you have plans to continue to work on this? I’d still like to see this happen.

We are about to merge code such that nightly begins running on Puma by default. My read of this thread is that this choice affects some of the design proposed within this change to handling the console. There appears to also have been some prior work in this area to get pieces completed. Is anyone able to summarize the current state of the art and leading candidate for the proposal on what we’d like to change?

1 Like

Given the lack of progress I at least made issue: Refactor #29539: Unbundle websockify - Foreman

note that there is also a ruby version https://github.com/novnc/websockify-other, so you might be able to remove the whole dependency on python

Now that we have proper websocket support, this should totally be doable.

1 Like

Last Friday I had a look at this. My goal was to continue using websockify but rather as a standalone project.

What I did was start a single instance on my Fedora instance:

# dnf install python3-websockify # installs 0.9.0
$ websockify --token-plugin JWTTokenApi --token-source /path/to/private.key 5910

Then I wrote some code in Foreman (patches to be published) to always use port 5910 and send a token encrypted with the same private key. This worked well for me.

What remains to be done:

  • Polish patches
  • Investigate using websockify behind Apache as a reverse proxy
  • Write systemd unit files to start websockify

It should be noted that currently websockify is too old in some places. We really need 0.9.0 for @UXabre’s JWTTokenApi plugin.

Probably not too complicated to package ourselves. It’s certainly better than to bundle it in Foreman itself.

1 Like

A while back I wrote some patch that does this. I plan to revisit it and clean it up later, but at least here is some basic working code:
https://github.com/theforeman/foreman/pull/8698

1 Like