diff --git a/global/post-tasks.d/018packages b/global/post-tasks.d/018packages index 9e25e69..57dff1a 100755 --- a/global/post-tasks.d/018packages +++ b/global/post-tasks.d/018packages @@ -1,16 +1,92 @@ -#!/bin/sh +#!/bin/bash + +CONFIG=${CONFIG:=/etc/puppet/cosmos-modules.conf} +CACHE_DIR=/var/cache/puppet-modules +MODULES_DIR=${MODULES_DIR:=/etc/puppet/cosmos-modules} +GIT_TAG_PATTERN=${COSMOS_UPDATE_VERIFY_GIT_TAG_PATTERN:-multiverse*} +export GNUPGHOME=/etc/cosmos/gnupg python -c "import yaml" 2>/dev/null || apt-get -y install python-yaml -if [ -f /etc/puppet/cosmos-modules.conf ]; then - grep -E -v "^#" /etc/puppet/cosmos-modules.conf | ( - cd /etc/puppet/modules && while read module src update; do - if [ ! -d /etc/puppet/modules/$module ]; then - echo $src | grep -q "://" && git clone $src $module || puppet module install $src - else - if [ "x$update" = "xyes" ]; then - echo $src | grep -q "://" && (cd /etc/puppet/modules/$module && git pull -q) || puppet module upgrade $src + +stage_module() { + rm -rf $CACHE_DIR/staging/$1 + git archive --format=tar --prefix=$1/ $2 | (cd $CACHE_DIR/staging/ && tar xf -) +} + +if [ -f $CONFIG ]; then + if [ ! -d $MODULES_DIR ]; then + mkdir -p $MODULES_DIR + fi + if [ ! -d $CACHE_DIR ]; then + mkdir -p $CACHE_DIR/{scm,staging} + fi + + # First pass to clone any new modules, and update those marked for updating. + grep -E -v "^#" $CONFIG | ( + while read module src update; do + # We only support git:// urls atm + if [ "${src:0:6}" = "git://" ]; then + if [ ! -d $CACHE_DIR/scm/$module ]; then + git clone -q $src $CACHE_DIR/scm/$module + elif [ -d $CACHE_DIR/scm/$module/.git ]; then + if [ "$update" = "yes" ]; then + cd $CACHE_DIR/scm/$module + git pull -q + else + continue fi - fi - done) + else + echo "ERROR: Ignoring non-git repository" + continue + fi + fi + done + ) + + # Second pass to verify the signatures on all modules and stage those that + # have good signatures. + grep -E -v "^#" $CONFIG | ( + while read module src update; do + # We only support git:// urls atm + if [ "${src:0:6}" = "git://" ]; then + # Verify git tag + cd $CACHE_DIR/scm/$module + TAG=$(git tag -l $GIT_TAG_PATTERN | sort | tail -1) + if [ "$COSMOS_VERBOSE" = "y" ]; then + echo "" + echo "Checking signature on tag ${TAG} for puppet-module $module" + fi + if [ -z "$TAG" ]; then + echo "ERROR: No git tag found for pattern '$GIT_TAG_PATTERN' on puppet-module $module" + continue + fi + fail=1 + git tag -v $TAG > /dev/null 2>&1 && fail=0 + if [ $fail == 0 ]; then + if [ "$COSMOS_VERBOSE" = "y" ]; then + # short output on good signature + git tag -v $TAG 2>&1 | grep "gpg: Good signature" + fi + # Put archive in staging since tag verified OK + stage_module $module $TAG + else + echo "################################################################" + echo "FAILED signature check on puppet-module $module" + echo "################################################################" + git tag -v $TAG + fi + fi + done + ) + + # Cleanup removed puppet modules from CACHE_DIR + for MODULE in $(ls -1 $CACHE_DIR/staging/); do + if ! grep -E -q "^$MODULE\s+" $CONFIG; then + rm -rf $CACHE_DIR/{scm,staging}/$MODULE + fi + done + + # Installing verified puppet modules + rsync --archive --delete $CACHE_DIR/staging/ $MODULES_DIR/ fi