From 389c04019b6df3dcbaf0c9d34a95601231895092 Mon Sep 17 00:00:00 2001 From: Fredrik Thulin Date: Thu, 19 Dec 2013 15:11:19 +0100 Subject: Add hiera-gpg for storing secrets used in templates. --- edit-secrets | 148 ++++++++++++++++++++++++++ global/overlay/etc/puppet/cosmos-modules.conf | 1 + global/overlay/etc/puppet/hiera.yaml | 18 ++++ global/pre-tasks.d/040hiera-gpg | 52 +++++++++ 4 files changed, 219 insertions(+) create mode 100755 edit-secrets create mode 100755 global/pre-tasks.d/040hiera-gpg diff --git a/edit-secrets b/edit-secrets new file mode 100755 index 0000000..08ec257 --- /dev/null +++ b/edit-secrets @@ -0,0 +1,148 @@ +#!/bin/bash + +set -e +umask 077 + +LAST_OUTPUT_FILENAME="/root/.last_edit-secrets_output" + +if [ "x$1" = "x" ]; then + echo "Syntax: $0 -l OR fqdn" + exit 1 +fi + +if [ "x$1" != "x-l" ]; then + host=$1 + + if [ ! -d $host ]; then + echo "$0: No host-directory for '$host' found - execute in top-level cosmos dir" + exit 1 + fi + + # Execute this very script, on a remote host + TMPFILE=$(mktemp) + if [ ! -f $TMPFILE ]; then + echo "$0: Failed creating temporary file" + exit 1 + fi + TMPFILE2=$(mktemp) + if [ ! -f $TMPFILE2 ]; then + echo "$0: Failed creating temporary file" + exit 1 + fi + + trap "rm -f $TMPFILE $TMPFILE2" EXIT + + ssh -t $host /var/cache/cosmos/repo/edit-secrets -l + scp -q $host:$LAST_OUTPUT_FILENAME $TMPFILE + + if grep ^"STATUS=UPDATED" $TMPFILE > /dev/null; then + # extract the path of the file that should be updated in the Cosmos repo + save_to=$(grep ^"SAVE_TO=" $TMPFILE | cut -d = -f 2-) + if [ ! -f $save_to ]; then + echo "$0: Output file $save_to doesn't exist" + echo " (leaving output in $TMPFILE)" + rm $TMPFILE2 + trap EXIT # clear trap command to preserve $TMPFILE + exit 1 + fi + # extract the GPG output + perl -e '$a = 0; while (<>) { $a = 1 if ($_ =~ /-+BEGIN PGP MESSAGE-+/); + print $_ if $a; $a = 0 if ($_ =~ /-+END PGP MESSAGE-+/); }' < $TMPFILE > $TMPFILE2 + + if ! grep "END PGP MESSAGE" $TMPFILE2 > /dev/null; then + echo "$0: Failed extracting PGP output from file $TMPFILE into $TMPFILE2" + exit 1 + fi + # use cat to preserve permissions etc. + cat $TMPFILE > $save_to + git add $save_to + + echo "" + echo "$save_to updated" + echo "" + else + echo "" + echo "Not updated" + echo "" + fi + + rm $TMPFILE $TMPFILE2 + + exit 0 +fi + +# +# Local execution on a host +# + +SECRETFILE=/etc/hiera/data/secrets.yaml.asc +GNUPGHOME=/etc/hiera/gpg/ +export GNUPGHOME + +GPG=`which gpg2 || true` +if [ ! -x "$GPG" ]; then + GPG=`which gpg || true` + if [ ! -x "$GPG" ]; then + echo "$0: gpg2 or gpg not found" + exit 1 + fi +fi + +TMPFILE=$(mktemp --tmpdir=/dev/shm) +TMPFILE2=$(mktemp --tmpdir=/dev/shm) + +if [ ! -f $TMPFILE ]; then + echo "$TMPFILE" + echo "$0: Failed creating temporary file" + exit 1 +fi +if [ ! -f $TMPFILE2 ]; then + echo "$TMPFILE2" + echo "$0: Failed creating temporary file 2" + exit 1 +fi + +trap "rm -f $TMPFILE $TMPFILE2" EXIT + +if [ ! -f "$GNUPGHOME/secring.gpg" ]; then + echo "$0: Secret keyring $GNUPGHOME/secring.gpg does not exist." + exit 1 +fi + +if [ -s $SECRETFILE ]; then + $GPG -d $SECRETFILE > $TMPFILE +fi + +cp $TMPFILE $TMPFILE2 +sensible-editor $TMPFILE +rm -f ${TMPFILE}~ ${TMPFILE2}~ + +echo "" +echo "" + +status=0 +cmp -s $TMPFILE $TMPFILE2 || status=1 +if [ $status -eq 0 ]; then + ( + echo "STATUS=NOT_CHANGED" + ) > $LAST_OUTPUT_FILENAME + echo "" + echo "$0: No changes detected" +else + # figure out this hosts gpg key id + recipient=$($GPG --list-secret-key | grep ^sec | head -1 | awk '{print $2}' | cut -d / -f 2) + + save_to="`hostname --fqdn`/overlay${SECRETFILE}" + echo "" + ( + echo "STATUS=UPDATED" + echo "SAVE_TO=$save_to" + echo "" + ) > $LAST_OUTPUT_FILENAME + $GPG --output - --armor --recipient $recipient --sign --encrypt $TMPFILE >> $LAST_OUTPUT_FILENAME + echo "" + echo "GPG output saved in $LAST_OUTPUT_FILENAME - save it in Cosmos as" + echo "" + echo " $save_to" + echo "" +fi diff --git a/global/overlay/etc/puppet/cosmos-modules.conf b/global/overlay/etc/puppet/cosmos-modules.conf index ea69171..af786c4 100644 --- a/global/overlay/etc/puppet/cosmos-modules.conf +++ b/global/overlay/etc/puppet/cosmos-modules.conf @@ -10,3 +10,4 @@ vcsrepo puppetlabs/vcsrepo no xinetd puppetlabs/xinetd no #golang elithrar/golang yes #python git://github.com/stankevich/puppet-python.git yes +hiera-gpg git://github.com/SUNET/hiera-gpg.git no diff --git a/global/overlay/etc/puppet/hiera.yaml b/global/overlay/etc/puppet/hiera.yaml index e69de29..cd619bb 100644 --- a/global/overlay/etc/puppet/hiera.yaml +++ b/global/overlay/etc/puppet/hiera.yaml @@ -0,0 +1,18 @@ +--- +:backends: - yaml + - gpg + +:logger: console + +:hierarchy: - %{env}/%{location}/%{calling_module} + - %{env}/%{calling_module} + - secrets.yaml + - common + + +:yaml: + :datadir: /etc/hiera/data + +:gpg: + :datadir: /etc/hiera/data + :key_dir: /etc/hiera/gpg diff --git a/global/pre-tasks.d/040hiera-gpg b/global/pre-tasks.d/040hiera-gpg new file mode 100755 index 0000000..e5de6da --- /dev/null +++ b/global/pre-tasks.d/040hiera-gpg @@ -0,0 +1,52 @@ +#!/bin/sh +# +# Set up a keyring for Hiera GPG +# https://github.com/crayfishx/hiera-gpg +# + +set -e + +GNUPGHOME=/etc/hiera/gpg +export GNUPGHOME + +if [ ! -f /usr/lib/ruby/vendor_ruby/gpgme.rb ]; then + apt-get update + apt-get -y install ruby-gpgme +fi + + +if [ ! -s $GNUPGHOME/secring.gpg ]; then + + if [ "x$1" != "x--force" ]; then + echo "" + echo "Automatic Hiera-GPG key generation DISABLED (to not block on missing entropy)" + echo "" + echo " Run \`$0 --force' manually" + echo "" + exit 0 + fi + + if [ ! -f /usr/bin/gpg2 ]; then + apt-get update + apt-get -y install gnupg2 + fi + + mkdir -p $GNUPGHOME + chmod 700 $GNUPGHOME + + TMPFILE=$(mktemp /tmp/hiera-gpg.XXXXXX) + cat > $TMPFILE <