Skip to content
This repository has been archived by the owner on Jun 5, 2020. It is now read-only.

Commit

Permalink
Add "fix" script to secure a master.
Browse files Browse the repository at this point in the history
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
Jeff McCune committed Oct 15, 2011
1 parent c1cc05f commit 18d52f4
Show file tree
Hide file tree
Showing 2 changed files with 120 additions and 0 deletions.
30 changes: 30 additions & 0 deletions README.markdown
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 #

90 changes: 90 additions & 0 deletions bin/step1_secure_the_master
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.

Copy link
@nigelkersten

nigelkersten Oct 17, 2011

Contributor

We should be requiring that the user puts in the new name explicitly here and fail if it is not provided.

This comment has been minimized.

Copy link
@jeffmccune

jeffmccune Oct 17, 2011

Contributor

@nigelkersten
Addressed in 09f2ccc


export PATH="/opt/puppet/bin:$PATH"

puppet resource service pe-httpd ensure=stopped hasstatus=true

This comment has been minimized.

Copy link
@nigelkersten

nigelkersten Oct 17, 2011

Contributor

Are we confident that using puppet service is the most reliable mechanism here? We do have some bugs on Debian with the service provider... :(

This comment has been minimized.

Copy link
@jeffmccune

jeffmccune Oct 17, 2011

Contributor

I say we keep it as is until we run into those bugs. It should work, I'd rather not prematurely optimize unless we know it's a problem for certain.


confdir="$(puppet master --configprint confdir)"
ssldir="$(puppet master --configprint ssldir)"
autosign="${confdir}/autosign.conf"

This comment has been minimized.

Copy link
@nfagerlund

nfagerlund Oct 17, 2011

Contributor

Autosign is a config setting too (http://docs.puppetlabs.com/references/latest/configuration.html#autosign), and if you set it to "true" it'll autosign everything even if autosign.conf doesn't exist. We should check the autosign setting the same way we check the rest of these settings.

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.

Copy link
@nigelkersten

nigelkersten Oct 17, 2011

Contributor

Should we be telling users why we're disabling autosign?

This comment has been minimized.

Copy link
@jeffmccune

jeffmccune Oct 17, 2011

Contributor

We actually don't need to disable autosign so long as certdnsnames is not configured... Should I just remove this chunk of code?

This comment has been minimized.

Copy link
@nigelkersten

nigelkersten Oct 17, 2011

Contributor

Yes.

This comment has been minimized.

Copy link
@jeffmccune

jeffmccune Oct 17, 2011

Contributor

@nigelkersten
Removed in 09f2ccc

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.

Copy link
@nigelkersten

nigelkersten Oct 17, 2011

Contributor

This should be 'puppet cert --generate' to work with older versions.

This comment has been minimized.

Copy link
@jeffmccune

jeffmccune Oct 17, 2011

Contributor

@nigelkersten
Changed to puppet cert --generate in ed647ea


# 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.

Copy link
@nigelkersten

nigelkersten Oct 17, 2011

Contributor

This should be 'puppet cert --generate' to work with older versions.

This comment has been minimized.

Copy link
@jeffmccune

jeffmccune Oct 17, 2011

Contributor

@nigelkersten
Changed to puppet cert --generate in ed647ea


# 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.

Copy link
@nigelkersten

nigelkersten Oct 17, 2011

Contributor

Am I right in thinking there's no problem if people successively run this script and end up with a whole series of CA/CRL certs in their pem file?

This comment has been minimized.

Copy link
@jeffmccune

jeffmccune Oct 17, 2011

Contributor

The script is not meant to be run more than once. The results will be unexpected if it is. Suggestions?

This comment has been minimized.

Copy link
@nigelkersten

nigelkersten Oct 17, 2011

Contributor

People will mess up this process.

We need to cope with that, either by providing an easy way to reset to the start, or by allowing this script to be run more than once.

My quick suggestion is:

  • Allow easy way to reset to the start.
  • Make script quit if it detects that it has already been run.

(assuming that's possible...)

This comment has been minimized.

Copy link
@jeffmccune

jeffmccune Oct 17, 2011

Contributor

We mess around with a lot of files. I think it'll be easiest to provide a way to reset and try again.

I'm going to add a section to the beginning of Step1 that makes a backup copy of every file we modify. I then plan to implement a "reset" script that stops the master, restores the files to their places, then starts the master again.

This should provide us with the "oh crap, I messed up, now what?" answer.

Sound good?

This comment has been minimized.

Copy link
@nigelkersten

nigelkersten Oct 17, 2011

Contributor

+1

This comment has been minimized.

Copy link
@jeffmccune

jeffmccune Oct 17, 2011

Contributor

@nigelkersten

I'd like this pull request to not be blocked by this discovered task. I've filed #2 to address it in a subsequent pull request.

This comment has been minimized.

Copy link
@nigelkersten

nigelkersten Oct 17, 2011

Contributor

ok.

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.

Copy link
@nigelkersten

nigelkersten Oct 17, 2011

Contributor

We should probably directly query "puppet --configprint manifest" rather than relying upon $confdir/manifests/site.pp.

What do we do about people with environments?

This comment has been minimized.

Copy link
@jeffmccune

jeffmccune Oct 17, 2011

Contributor

The script is already using the manifest configuration setting rather than reconstructing it from confdir in 990c1fa.


# 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."

0 comments on commit 18d52f4

Please sign in to comment.