RFC: Redesign Certificate Handling within Foreman Deployments

In general looks good, only question I have is regarding the puppet usecases and how do they fit in here?

I didn’t forget your question :slight_smile: But I did need to do some further digging and thinking around designs to come back and propose some technical follow up.

Certificate Management

First, here are two options around how I have been thinking about how to approach certificates input to the installer and propagated to the puppet modules from a strategy perspective. My overarching design principle is:

Separate creation of certificates from the management of the certificates

Option 1: Copy and manage

Steps

  • User provides certificates as input
  • Module copies those certificates to the “correct” location and manages them (e.g. user, group, perms)

Notes

  • If a user removes the certificates installation will fail next run as it won’t find the original certificate
  • If users removes the certificates, services will continue to function through restarts (since copies will remain in tact)
  • Any certificate changes require installer re-run

Option 2: Manage the files directly

Steps

  • User provides certificates as input
  • Modules manages the input certificate paths directly (e.g. user, group, perms)

Notes

  • Could gate behind a manage_certificates flag for advanced users
  • One downside is user has to make they put certificates in an accessible location
  • One downside is the location of certificates become unpredictable on a given installation
  • One downside is potentially competing services (e.g. need multiple groups, different permissions)
  • One upside/downside is user has more direct control, when certificates change they need only restart services
    • However, for services that use certificate stores those stores have to be re-generated anyway
  • If a user removes the certificates, services will fail on any restarts, installation will fail next run

Certificate store Management

For some services, there are advanced certificate storage mechanisms in use such as keystores and NSS databases. The design here is around moving the creation and management of those stores into the modules for the services themselves and focus on the input to the module being the needed set of certificates. This keeps the user from having to create and manage these more complex entities and focus on just certificates. Further, given these stores need properties set on them like user and group for example it is easier for the module to manage this and ensure everything is correctly set up for the service to operate correctly.

I’ve opened a proof of concept PR to show this in action: POC: Manage truststore completely within module by ehelms · Pull Request #195 · theforeman/puppet-candlepin · GitHub

How does this apply to Puppet certificates (and Katello)?

Today Foreman defaults to using certificates generated by Puppet and using the paths on disk that Puppet creates. Management of the certificate access is handled by ensuring the foreman user is part of the puppet group. In Option 1 above, we would copy these Puppet certificates to a standard location (e.g. /etc/foreman) and set user/group/perms on them accordingly. In Option 2, we would continue the model we have today but based on user input rather than the current defaults.

That gets me to some of my thinking around how do we split apart the Foreman default to Puppet certificate paths and level set Puppet certificates with user defined certificates or some other provider such as Katello’s default certificate setup or something new in the future.

I am not sure yet on that point. For Puppet, the creation of the certificates and the paths are handled within the theforeman-puppet module and thus could be used as inputs to Foreman’s parameters for SSL. This same problem applies to Katello where we hard-code the certificate paths in the answers file.

How do we orchestrate that and make it easier for the user inside the installer?

I have opened a draft POC PR with this question to help try to gather some design discussions closer to the code as I think that can be easier to think and talk about.