Everyone who has been using Puppet with a self-signed CA for over 5 years knows the dreaded time: the time when the CA must be renewed.
Renewing the CA
The traditional approach is to create a new CA, and then use another mean to renew the certificates for all the nodes (SSH, MCollective, Ansible, etc.).
Another possibility is to keep the same CA keys and generate a new CA certificate. There is actually an official module to do that. This module allows you to easily revive a CA that is about to expire in such a way that the new CA certificate is valid for current node certificates. As a result, you don’t need to renew the node certificates right away; you only need to distribute the new CA certificate to ensure the cached version does not expire!
There is however a consequence: node certificates will start to expire. Nodes over 5 years old will expire as soon as the CA expires. And so they need to be renewed, too.
Renewing the node certificates
What if the Puppet agent itself could ensure its certificate is always valid? This can be achieved using two things:
- an autosign policy;
The former is a standard Puppet feature, with a simple principle: embark a secret in the Puppet CSR, which will be checked by a script on the CA.
This approach allows to easily automate node provisioning by making nodes automatically register into Puppet.
The simplest form uses a shared password in the
csr_attributes.yaml file on the Puppet node.
Once you have put together a way to autosign certificates, let’s see how to automatically renew these certificates. We’ll use the puppet_certificate Puppet module for that. Here is the kind of code you could use:
This code will:
- manage the
csr_attributes.yamlfile to inject the psk into it;
- manage the Puppet certificate of the node.
- If the psk is modified, the certificate will be recreated;
- The certificate will automatically be renewed 20 days before it expires (using
ensure => valid);
Note that this only works if the certificate is cleaned from the Puppet CA before it gets regenerated. This is the point of the
clean => true attribute. By default, however, the Puppet CA does not accept remote cleaning of certificates. You can allow nodes to clean their own certificates (and no other) by adding this to your Puppetserver’s
While it is possible to use a simple shared password in the
csr_attributes.yaml for autosigning, it means all your nodes will contain that psk, which is valid to create new certificates on the Puppet CA. This is not very secure, and this can be improved by using unique tokens for each node, so that a token can only be used to generate a certificate for a specific node.
You could achieve this with tools such as Vault. Another idea is to generate a composite secret on the Puppet master by mixing the psk with the certname and possibly any certificate extension you want to enforce. You then need to adapt your autosign policy script to generate the same composite secret, which ensures that each node can only generate its own certificate, without changing its extensions.