Changing the Foreman Proxy registration authentication

Problem statement

Currently creating a Foreman Proxy requires OAuth credentials. This is the only usage of OAuth within Foreman and doesn’t provide a nice experience for users. It may also be a security concern because the credentials provide admin privileges.

Current implementation

When the user wants to install a new Foreman Proxy, the common workflow is to run foreman-installer --no-enable-foreman --no-enable-foreman-cli --foreman-proxy-foreman-base-url https://foreman.example.com --foreman-proxy-oauth-consumer-key $KEY --foreman-proxy-oauth-consumer-secret $SECRET.

The OAuth credentials are used to authenticate to the Foreman API to create a smart_proxy entry. It’s also used to verify the features Foreman has recognized. Outside of that, it’s not used.

On a technical level it uses the Puppet foreman_smartproxy type / provider. This calls the REST API with the OAuth credentials. First of all, it calls GET api/v2/smart_proxies with name=#{name} as search. If this exists, it calls PUT api/v2/smart_proxies/#{id}/refresh (and PUT api/v2/smart_proxies/#{id} to update the URL if needed). When it doesn’t, POST api/v2/smart_proxies is called.

The feature verification works by taking the features Foreman reports in the smart_proxy API. The installer knows what features to expect. If there’s a mismatch, the installer will fail. This can happen when a feature on Foreman Proxy failed to initialize or when Foreman lacks a plugin that Foreman Proxy has. For example, when Foreman Proxy installs REX but Foreman doesn’t have REX installed.

When a smart_proxy entry is created in Foreman (both UI and API), it always refreshes the features. This means the Foreman Proxy must be online and functioning.

OAuth is used because an API request to create a Smart Proxy needs to be authenticated. Just trusting the SSL certificate is insufficient because a CA may be used for more than just the Foreman infrastructure. Not every host should be a Smart Proxy.

Implementation

Rather than creating the smart_proxy entry via the API, it should be possible to precreate the entry but not refresh its features. To achieve this, the form and API in Foreman should gain a field to not refresh the features as part of the save.

The API should also be modified to allow a Smart Proxy to get its own data and refresh its features. The authentication can happen via the SSL certificates already in place (used to authenticate when creating a config_report among others).

Then the foreman_proxy provider should be modified to use SSL certificates to authenticate.

Considerations

This covers the manual way, but still requires OAuth for a fully automatic deployment where a host is provisioned and a new Foreman Proxy is created automatically. Either by using Puppet (outside of the installer) or calling the installer with hardcoded credentials or yet another way.

Instead of OAuth, the authentication can also be changed to use personal access tokens. The downside of that is that OAuth it “just works” with Puppet when using a Puppetmaster because you can provision Foreman with a key/secret, cache those values and reuse them. That now happens and means adding a Foreman Proxy is trivial.

1 Like

Why is this necessary? Just because

?

That’s a great idea.

Correct. Refreshing features means calling the Foreman Proxy which means it must be online. If you create the entry before provisioning the Foreman Proxy, it can’t be online.

I’m all for dropping oauth. I like the fact, we’d be able to create proxies, that do not live yet. Certificates may be a good option but when you mentioned tokens, I’d like that option even more, due to its simplicity. We could have a service user with limited permissions. The same certificate could potentially be used in other endpoints, e.g. facts uploading which is potentially destructive operation. The authorization there is relying on feature being present on the proxy.

But whatever leads to dropping oauth (since we don’t use it elsewhere and only use in very limited way) and ability to create a proxy which is not reachable at moment of creation is a good improvement.

1 Like

Am I on the right track with how I interpret the proposed workflow:

  1. As a user, I request to create a new proxy
  2. I am handed a set of client certificates that will authenticate the proxy
  3. I provision and install my proxy through whatever means necessary handing it the client certificates
  4. The proxy reaches out to Foreman to say here I am and this is who I am
  5. Foreman authenticates and links the two
1 Like

And when I think about the ssl vs tokens a bit more, tokens would be more complicated change, certs are already there and it should be just few lines of code. Also certs wouldn’t make it harder in case we decide to use tokens later.