Puppet Enterprise with Intermediate CA

Puppet Enterprise with Intermediate CA

In many environments regulations require to intercept SSL traffic. This is necessary to enable firewalls or other devices to detect malicious activities. Puppet Enterprise in its default installation creates its own CA and maintains it. But this makes it impossible to intercept the SSL traffic between Puppet Enterprise and its agents without a man-in-the-middle attack is detected. To solve this problem, Puppet Enterprise can use your own Intermediate CA during installation.

The post will guide you through the process of creating your own Root CA. The next step will explain how to create an Intermediate CA from the newly created Root CA. I will attach my openssl.cnf files for my Root CA and my Intermediate CA to make it more easy to create these CAs.

Before we begin here’s the environment we will work in. The OS is a CentOS 7 server running the CAs. Puppet Enterprise will be installed on a Ubuntu 18.04 server. Out intermediate CA I will name „puppet“.

Environment on our CA server

On our server hosting our CA, we have to create some directories needed by our CA. Here’s an example directory layout I will use:

> cd /root
> mkdir -p ca/root_ca        # our root ca
> mkdir -p ca/puppet         # out intermediate ca
> cd root_ca
> mkdir certs crl newcerts private csr > chmod 700 private > touch index.txt > echo 1000 > serial
> echo 1000 > crlnumber

# setup of intermediate ca
> cd ../puppet
> mkdir certs crl newcerts private csr
> chmod 700 private
> touch index.txt
> echo 1000 > serial
> echo 1000 > crlnumber

Next we will create a password file and encrypt that file. To keep things easy we will use the same password file for the Root CA and the Intermediate CA. In production environments you should have different files for each CA. Encryption of the password file needs a password for encryption. You have to enter this password twice.

cd /root/ca
# this secret we will use to protect private keys
> echo "your secret" > passfile 
# You need to enter a encryption password twice
> openssl enc -aes-256-cfb8 -salt -in passfile -out passfile.enc 
> chmod 0400 passfile passfile.enc

You can delete the file with the plaintext password. In our case the passfile file.

Now we are ready to create our CAs.

Creating a Root CA

If you already have your own Root CA please skip this step.

First we need to create an openssl.cnf file for our new Root CA. You can download the file root-openssl.cnf to make setup easier. But you can create an openssl.cnf file yourself as well.

The openssl.cnf file will be located in the /root/ca/root_ca directory. 

Private key for Root CA

Now we are ready to create the private key for out new Root CA. I strongly recommend to use 4096 bits for the keys of your Root CA and your Intermediate CA.

> cd /root/ca/root_ca
> openssl genrsa -aes256 \
-passout file:/root/ca/passfile.enc \
-out private/cakey.pem 4096
> chmod 400 private/cakey.pem

The passphrase for this key will be taken from the encoded passfile.

Create certificate for Root CA

With our newly created private key we can create the public certificate of our Root CA. You have to fill several fields for your CA. I recommend, to put something like „My company Root CA“ into the Common Name field.

> cd /root/ca/root_ca
> openssl req -config openssl.cnf -new -x509 -days 3650 \
-extensions v3_ca \

-passin file:/root/ca/passfile.enc \
-key private/cakey.pem \
-out certs/cacert.pem

Verify certificate for Root CA

Now we verify our new certificate.

> openssl x509 -noout -text -in certs/ca.cert.pem

You should see some informations about your certificate. If there are errors displayed something went wrong.

That’s it. You have your Root CA created. Let’s continue with creating our Intermediate CA.

Create CRL for Root CA

For our further use with Puppet Enterprise we need CRLs (Certificate revocation lists). We can create the one for our Root CA with the following commands:

> cd /root/ca/root/ca
> openssl ca -config openssl.cnf \
-passin file:/root/ca/passfile.enc \
-gencrl -out crl/crl.pem

The command will create a crl.pem file. We have no revoked certificates so far but we need this file later to install Puppet Enterprise.

Create an Intermediate CA

With our Root CA we are now able to create an Intermediate CA.

First we need to create an openssl.cnf file for our new Intermediate CA. You can download the file intermedite-openssl.cnf to make setup easier. But you can create an openssl.cnf file yourself as well.

The openssl.cnf file will be located in the /root/ca/puppet directory.

Create private key for Intermediate CA

To create the private key for the Intermediate CA do the following:

> cd /root/ca/puppet
> openssl genrsa -aes256 \
-passout file:/root/ca/passfile.enc \
-out private/puppet.cakey.pem 4096

> chmod 400 private/puppet.cakey.pem
To be able to distinguish between Root CA and Intermediate CA we use „puppet“ in the filenames of the Intermediate CA.

Create CSR for Intermediate CA

Now we have to create a Certificate Signing Request (CSR) for our Intermediate CA. I recommend, to put something like „My company Intermediate CA Puppet“ into the Common Name field. The „challenge password“ and the „optional company name“ fields you can leave empty.

> cd /root/ca/puppet
> openssl req -config openssl.cnf -new -sha256 \
-passin file:/root/ca/passfile.enc \
-key private/puppet.cakey.pem \
-out csr/puppet.csr.pem

Create certificate for intermediate CA

Now we can sign the CSR for our Intermediate CA. It is important to use openssl.cnf file of the Root CA to do this! 
> cd /root/ca/root_ca            # be careful here to do this in the directory of the root ca
> openssl ca -config openssl.cnf -extensions v3_intermediate_ca \
-days 2650 -notext -batch \
-passin file:/root/ca/passfile.enc \
-in ../puppet/csr/puppet.csr.pem \
-out ../puppet/certs/puppet.cacert.pem

Verify certificate for Intermediate CA

To verify the certificate do the following:

> cd /root/ca/puppet
> openssl x509 -noout -text \
-in certs/puppet.cacert.pem

You should see output similar to this: „intermediate.cert.pem: OK“

Create CRL for Intermediate CA

As we did for the Root CA we need to create a CRL for the Intermediate CA as well. To create the CRL for our Intermediate CA do the following:

> cd /root/ca/puppet
> openssl ca -config openssl.cnf \
    -passin file:/root/ca/passfile.enc \
    -gencrl -out crl/puppet.crl.pem

This CRL we need for the Puppet Enterprise installation later.

 

Installing Puppet Enterprise

There’s a documentation on how to install Puppet Enterprise with your own Intermediate CA. On how to install Puppet Enterprise with a self-signed Intermediate CA please refer to this documentation. Please read carefully about what you have to take care yourself when using you own Intermediate CA.

For the following I assume that you have a Ubuntu 18.04 server prepared. This server should comply to the system requirements for Puppet Enterprise. I will also assume that you have your Puppet Enterprise installer unpacked into the /var/tmp directory.

Preparations on our CA server

On our CA server we have to prepare some files for the Puppet Enterprise installation. We will copy these files into the /root/puppet_install directory.

The following steps have to be done ou your server hosting your newly created CAs.

Create a Cert Bundle

> mkdir -p /root/puppet_install
> cat /root/ca/puppet/certs/puppet.cacert.pem > /root/puppet_install/cert_bundle.pem
> echo >> /root/puppet_install/cert_bundle.pem
> cat /root/ca/root_ca/certs/cacert.pem >> /root/puppet_install/cert_bundle.pem
> echo >> /root/puppet_install/cert_bundle.pem

Create a CRL Bundle

> cat /root/ca/puppet/crl/puppet.crl.pem > /root/puppet_install/crl_bundle.pem
> echo >> /root/puppet_install/crl_bundle.pem
> cat /root/ca/root/ca/crl/crl.pem >> /root/puppet_install/crl_bundle.pem
> echo >> /root/puppet_install/crl_bundle.pem

Remove passphrase from Intermediate CA private key

Puppet Enterprise needs the private key without passphrase. We protected out private key with a passphrase. We copy the private key and remove the passphrase during copy.

> openssl rsa -in /root/ca/puppet/private/puppet.cakey.pem \
-out /root/puppet_install/puppet-ca.key \
-passin file:/root/ca/passfile

Now we have all necessary files for the installation of Puppet Enterprise gathered. Copy the whole directory ro the server where Puppet Enterprise will be installed.

> scp -r /root/puppet_install <user>@<puppetserver>:/tmp/

Install Puppet Enterprise

On the puppet server move the directory to /root.

> mv /tmp/puppet_install /root/
> chmod 700 /root/puppet_install

Now we prepare our pe.conf file to use with the Puppet Enterprise installer.

Create a file /root/pe.conf with at least the following content. If you need some more settings in the pe.conf file please consult the Puppet Documentation.

{
"console_admin_password": "mypassword"
"puppet_enterprise::puppet_master_host": "<puppet server fqdn>"

"pe_install::signing_ca": {
"bundle": "/root/puppet_install/cert_bundle.pem"
"crl_chain": "/root/puppet_install/crl_bundle.pem"
"private_key": "/root/puppet_install/puppet-ca.key"
}

}

The pe.conf file contains useful information for the Puppet Enterprise installer.

Change into the puppet enterprise installer directory and do the following:

> ./puppet-enterprise-installer -c /root/pe.conf

If everything is ok with your Intermediate CA the installer will work fine. If there are problems with the certificates you will see errors during the install process. Please look into the installer’s logfile to see what’s wrong.

Check auth.conf file

After Puppet Enterprise install is finished check the /etc/puppetlabs/puppetserver/conf.d/auth.conf file. Open the file and search for entries for the url /puppet-ca/v1/certificate_revocation_list. Currently in my installation I found this entry two times. Make sure that the type is set to regex. Here’s an example how that should look like:

 "match-request": {
"method": "put",
"path": "^/puppet-ca/v1/certificate_revocation_list$",
"type": "regex"
},

"match-request": {
"method": [
"put"
],
"path": "^/puppet-ca/v1/certificate_revocation_list$",
"query-params": {},
"type": "regex"
},
"name": "puppetlabs certificate revocation list",
"sort-order": 500

If you change these entries restart your Puppet server.

Maintain CRLs in Puppet Enterprise

As you use your own Intermediate CA you have to take case to upload new CRLs to Puppet Enterprise. Here’s a short example script to upload CRLs to Puppet Enterprise.

#!/bin/bash

if [ $# -ne 1 ] ; then
prog=`basename $0`
echo "usage: $prog <crl file>"
exit 2
fi
type_header='Content-Type: text/plain'
cert="$(puppet config print hostcert)"
cacert="$(puppet config print localcacert)"
key="$(puppet config print hostprivkey)"
uri="https://$(puppet config print server):8140/puppet-ca/v1/certificate_revocation_list"
curl --insecure --cert "$cert" --cacert "$cacert" --key "$key" \
--header "Content-Type: text/plain" --header "Accept: text/plain" \
--request PUT --data "@$1" "$uri"
echo
exit 0

The best way is to create CRLs automatically, upload the new CRL to the Puppet Enterprise server and run the above script on that server.

Full script

I created a shell script with all the commands above to create a Root CA and an Intermediate CA. The script will also create the files needed for the Puppet Enterprise installer. You can download the zip file here but you are strongly advised to review it before you use it! I’m not responsible for whatever will happen.