-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This script takes a PE master and implements the steps required to secure it. A new certificate is generated using a new DNS name, a new CA is generated, and the PE HTTPD configuration is configured to trust both the new and the old CA. After running this process, an existing Puppet Agent system should be able to reconnect to the master by simply updating its --server setting. e.g. puppet agent --test --server puppetmaster.new
- Loading branch information
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
# CVE-2011-3872 Module # | ||
|
||
This module provides two main pieces of functionality: | ||
|
||
* Help me get secure | ||
* Once secure, help me migrate to a new CA | ||
|
||
# Quick Start (PE) # | ||
|
||
PE Only Scripts. These are specifically designed to work with PE. These | ||
scripts will need to be adapted to help FOSS users and customers. | ||
|
||
On a Puppet Master, the `step1_secure_the_master` script should be run first. | ||
This script will perform the following actions: | ||
|
||
* Stop the Puppet Master (Apache) | ||
* Issue a new SSL cert for the master with a unique name | ||
* Issue a new CA with a unique name | ||
* Swap the new CA into place. | ||
* Reconfigure fileserver and puppet.conf on the master to use the new name. | ||
* Start things back up. | ||
|
||
At this point, existing Puppet Agent's should be able to reconnect to the master with a simple: | ||
|
||
puppet agent --test --server puppetmaster.new | ||
|
||
e.g. the only change to clients is the server configuration setting. | ||
|
||
# Migrate an Agent # | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
#! /bin/bash | ||
# | ||
set -e | ||
set -u | ||
|
||
# As LAK points out, configuring Puppet to communicate with a master | ||
# using a name that is not in CN or CERTDNSNAMES will secure the | ||
# entire system again. | ||
# We need a new certificate to do this... | ||
old_master_cert="$(puppet master --configprint certname)" | ||
new_master_cert="${1:-"${old_master_cert}.new"}" | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong. |
||
|
||
export PATH="/opt/puppet/bin:$PATH" | ||
|
||
puppet resource service pe-httpd ensure=stopped hasstatus=true | ||
This comment has been minimized.
Sorry, something went wrong.
nigelkersten
Contributor
|
||
|
||
confdir="$(puppet master --configprint confdir)" | ||
ssldir="$(puppet master --configprint ssldir)" | ||
autosign="${confdir}/autosign.conf" | ||
This comment has been minimized.
Sorry, something went wrong.
nfagerlund
Contributor
|
||
puppetconf="${confdir}/puppet.conf" | ||
# The new CA CN _must_ be different than the old CA CN | ||
old_ca_cn="$(puppet master --configprint ca_name)" | ||
|
||
# Make sure autosign is off. | ||
echo "Making sure autosign is turned off ... (${autosign})" | ||
if [[ -e "${autosign}" ]]; then | ||
mv "${autosign}" "${autosign}.disabled" | ||
echo "Disabled autosign by moving $autosign to ${autosign}.disabled" | ||
This comment has been minimized.
Sorry, something went wrong.
This comment has been minimized.
Sorry, something went wrong.
jeffmccune
Contributor
|
||
else | ||
echo "Autosign does not appear to be enabled. (${autosign} does not exist)" | ||
fi | ||
|
||
# Make sure certdnnames are off. | ||
echo "Making sure certdnsnames are turned off ... (${puppetconf})" | ||
perl -p -l -i.backup1 -e 's/^(\s*)(certdnsnames\b.*$)/$1# Disabled to mitigate CVE-2011-3872\n$1# $2/' "${puppetconf}" | ||
echo "Reconfiguring puppet.conf to switch names..." | ||
perl -p -l -i.backup2 -e 's/^(\s*)(.*?=)(\s+)('"${old_master_cert}"')\s*$/$1# Name Fix: $4 => '"${new_master_cert}"'\n$1$2$3'"${new_master_cert}"'/g' "${puppetconf}" | ||
|
||
# Generate the new SSL certificate | ||
# NOTE (THIS STEP we need to get a good, new name for the end user) | ||
puppet cert generate "${new_master_cert}" | ||
This comment has been minimized.
Sorry, something went wrong.
nigelkersten
Contributor
|
||
|
||
# Move the SSL directory. | ||
oldssldir="${ssldir}.previous" | ||
echo "Moving ${ssldir} to ${oldssldir}" | ||
mv "${ssldir}" "${oldssldir}" | ||
|
||
# Generate the new CA | ||
echo "Generating the new CA ..." | ||
puppet cert generate --ca_name "Puppet CA: ${new_master_cert}" "${old_master_cert}" | ||
This comment has been minimized.
Sorry, something went wrong.
nigelkersten
Contributor
|
||
|
||
# Copy the new, secure SSL certificate generated by the OLD CA into the location | ||
# used by the PE Apache server | ||
echo "Copying puppet master's secured certificate into place..." | ||
for d in certs ca/signed private_keys public_keys; do | ||
# NOTE, we copy the new cert, e.g. "puppetmaster.secure" to the old name, e.g. "puppetmaster" | ||
cp -p "${oldssldir}/${d}/${new_master_cert}.pem" "${ssldir}/${d}/${old_master_cert}.pem" | ||
done | ||
|
||
# Configure Apache to trust old clients: | ||
cat "${oldssldir}"/certs/ca.pem >> "${ssldir}"/certs/ca.pem | ||
This comment has been minimized.
Sorry, something went wrong.
nigelkersten
Contributor
|
||
cat "${oldssldir}"/ca/ca_crl.pem >> "${ssldir}"/ca/ca_crl.pem | ||
|
||
# The first CRL listed in $hostcrl needs to be issued by the | ||
# same CA that issued the certificate of the server the agent is talking to. | ||
# if it doesn't the agent will refuse to connect. | ||
echo "Shuffling around the CRL's for the agent (hostcrl)" | ||
mv "${ssldir}"/crl.pem "${ssldir}"/crl.pem.new | ||
cp -p "${oldssldir}"/crl.pem "${ssldir}"/crl.pem | ||
cat "${ssldir}"/crl.pem.new >> "${ssldir}"/crl.pem | ||
|
||
# PE configures the fileserver by default in site.pp | ||
# Check for this and patch it. | ||
echo "Patching site.pp to update fileserver resources" | ||
perl -p -l -i.backup -e 's/\b(server\s*=>\s*.*?)('"${old_master_cert}"')(\W*)/$1'"${new_master_cert}"'$3/g' "${confdir}/manifests/site.pp" | ||
This comment has been minimized.
Sorry, something went wrong.
nigelkersten
Contributor
|
||
|
||
# At this point, existing agents should be able to communicate with the master. New certificates | ||
# will be signed by the new CA. | ||
puppet resource service pe-httpd ensure=running hasstatus=true | ||
|
||
echo "" | ||
echo "Your master has been reconfigured with a new name to mitigate CVE-2011-3872" | ||
echo "Your agents will not work until they're configured to use this new name." | ||
echo "You can expect to receive the error: Failed to generate additional resources using 'eval_generate': hostname was not match with the server certificate" | ||
echo "If your name service is configured already, your agents should work with the following command:" | ||
echo "" | ||
echo "puppet agent --test --server ${new_master_cert}" | ||
echo "" | ||
echo "This command may help you switch your puppet.conf on all of the agents." | ||
|
We should be requiring that the user puts in the new name explicitly here and fail if it is not provided.