I started playing with Puppet recently in an effort to write some “self contained” installation scripts that didn’t require a lot of infrastructure to support them. I ended up developing a pattern of code that allowed me to bundle the entire set of scripts, properties, and even protected encryption keys into a single Git repository.
The pattern makes use of a few basic requirements and has a minimal set of steps to build up. My example scripts make use of Puppet, Git, and eHiera (eYAML) for encrypted properties. The basic steps are:
- Install puppet and git
- Fetch a repository
- Run puppet configuration scripts
- (optional) Install eyaml encryption keys
- Run custom puppet modules to install/configure other things
I’ve successfully used this pattern for installing Jenkins, Sonar, and mySQL on a current project of mine.
Full directions with a working example are available on Github:
The actual steps are outlined in the README file in the repository. I’ll explain some of the trickier parts here.
The first tricky part is getting Hiera to work properly without having to replicate or install the hiera files in some central default location (i.e., /etc/hiera or /etc/puppet). This was useful since I wanted all the properties to be maintained in the Git repository.
The trick is to use a combination of a specific hiera.yaml file combined with invocation options from the command line.
Then, invoke puppet with
puppet apply ... --hiera_config `pwd`/hiera/hiera.yaml ...
Note that this means that you need to clone/checkout the puppet repository into the very specific path of /opt/software/puppet-modules/puppet-solo to make this all work.
The second trick was to set up eHiera and eYaml to work properly. eHiera allows us to store encrypted property values in hiera files then reference them in puppet manifests.
The first step in setting this up also involves the hiera.yaml file:
# eyaml must be first :backends: - eyaml - yaml :eyaml: :datadir: /opt/software/puppet-modules/puppet-solo/hiera :pkcs7_private_key: "/etc/puppet/secure/keys/private_key.pkcs7.pem" :pkcs7_public_key: "/etc/puppet/secure/keys/public_key.pkcs7.pem" :extension: 'yaml' :yaml: :datadir: "/opt/software/puppet-modules/puppet-solo/hiera"
This leverages the step I mentioned above with the ‘datadir’ setup. In this case, however, I chose to put the secure PEM keys into a central location. This is primarily because these keys need to be protected very carefully. I generally avoid, at all costs, keeping unprotected keys in source repositories. Which leaves a hard dilemma. The hiera values we want to store in our repository need to be encrypted with a known set of keys. So how do we distribute those keys in a secure manner without compromising them?
In my pattern, I chose to store the keys in a password encrypted ZIP file, then simply protect the password to that ZIP file and store it elsewhere. The encrypted ZIP file gets stored in repository for easy distribution. To setup our self-contained puppet and hiera module, my instructions require unpacking the ZIP file with the keys into a set location that can be referenced.
In complete and utter contradiction to that principle, I’ve stored the password to the ZIP file right next to the file for simple access and reference it in the README.md file. DON’T EVER, EVER DO THIS IN ANYTHING EXCEPT A TUTORIAL SITUATION.
Normally, I have the password stored in a secure password database (I use Keepass) and use it when I install/configure a new server as a manual step. If you end up using this pattern, then please, PLEASE, P L E A S E regenerate a new set of keys for yourself and protect them properly.
Configuring Puppet and Pre-requisites
I guess the only other “trick” I used was in getting Puppet actually setup properly, then use it to execute the module I actually care about.
First, I install a couple basic pre-requisites (note: I did all this on RedHat linux):
sudo yum install puppet git
Next, I wrote some simple puppet scripts that don’t have many requirements, but install all the other stuff I need. The actual code is in the git repository, but it installed eHiera, eYaml, and a few other dependencies. I run it as an individual step:
sudo puppet apply --modulepath=`pwd`/modules manifests/install-puppet.pp
At this point, I unpack of the keys from the encrypted ZIP file when/if I need to use encrypted property.
sudo unzip -d /etc/puppet/secure/keys ./hiera/compromised-hiera-keys.zip
After that is set up, I can get to the business I actually want: install my software.
sudo puppet apply --modulepath=`pwd`/modules:/etc/puppet/modules --hiera_config `pwd`/hiera/hiera.yaml manifests/custom-site.pp
In my tutorial example, I only have a few basic steps in it to provide the basic framework. The final “trick” here is to include your custom module path as well as the system module path, particularly if you use any standard puppet modules that might be installed there (i.e., with your ‘puppet-install’ script).
And that’s it … four simple commands that pass off control to Puppet and install/configure whatever you want.