Skip to content

Instantly share code, notes, and snippets.

@ahpook
Created August 30, 2011 22:14
Show Gist options
  • Save ahpook/1182243 to your computer and use it in GitHub Desktop.
Save ahpook/1182243 to your computer and use it in GitHub Desktop.
Use a generic client certificate with puppet

The problem

There's enough trouble with puppet's ssl model (mandatory client certs) that people go and do odd things to get around it. The primary problem is that for lab/preproduction environments, if you reinstall machines frequently, you lose access to the private key that generated the original cert but (absent some puppet cert --clean [node] operation) the cert still exists, leading to the dreaded Retrieved certificate doesn't match private key error.

A solution

Generate a single client certificate which all your nodes use, and have the master determine node names from facter rather than the SSL DN. This way you can re-install nodes with impunity and as long as your bootstrap plops down the correct config and the cert+key, you don't have any more SSL issues.

The caveats

If you have autosign turned on, this change represents a shift in security tradeoffs: you can turn off autosign and therefore more tightly control which clients can talk to your server because they need to have your client cert+private key on them, but at the cost that any node with the cert+key can request any other node's catalog. So think through the trade-offs, but IMO if you are autosigning anyway, heavily firewalled, and dealing with rapid host recycling, this is a viable approach.

Note that this depends on puppetlabs bug#2128 being implemented, so you need to be running at least version 2.6.9 on client and server.

The procedure

  • generate a certificate+keypair on the master:
     puppet cert --generate generic-hostcert.mydomain.com
  • transfer the resulting $ssldir/{private_keys,ca/signed}/generic-hostcert.mydomain.com.pem to the client's $ssldir/{private_keys,certs}/ directories (in that order!)

  • set up a server instance with the following changes to puppet conf:

     [master]
       node_name = facter
  • Make the following change to auth.conf (so the generic cert is allowed to retrieve anyone's catalog):
    *** /etc/puppet-test/auth.conf  2010-09-29 10:58:34.000000000 -0700
    --- ./auth.conf 2011-08-30 13:53:39.000000000 -0700
    ***************
    *** 51,58 ****
    --- 51,59 ----
    # allow nodes to retrieve their own catalog (ie their configuration)
    path ~ ^/catalog/([^/]+)$
    method find
    allow $1
    # allow the generic cert to retrieve any node's catalog
    + allow generic-hostcert.mydomain.com
    #allow *
  • invoke the client with the following arguments/commands:
    [agent]
       certname = generic-hostcert.mydomain.com
       node_name = facter
       node_name_fact = fqdn
  • run puppet against the server instance, note that the catalog request comes in for /production/catalogs/hostname.mydomain.com, external nodes is invoked correctly, etc even though the cert name is the generic one.
@lucasdiedrich
Copy link

For the record, i had to use the option below to work:

use-legacy-auth-conf: true

@dannykansas
Copy link

A huge shot in the dark here, but if this cert method was implemented years ago and the cert has now expired, what is a good method for updating the generic cert?

CA is already taken care of (that's well documented elsewhere, see: puppetlabs/certregen and flyinglotus.io's article, if anyone runs across this needing help on the CA aspect).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment