From 9b801d3be8e0268994169729cf5d5dd4600367cb Mon Sep 17 00:00:00 2001
From: Stefan Wold <ratler@stderr.eu>
Date: Sat, 22 Feb 2014 18:29:41 +0100
Subject: git tag gpg signature validation of puppet modules

Before staging a puppet module for install the latest git tag is
verified using the available gpg key identities. The git tag pattern
can be overriden using a fourth argument in cosmos-modules.conf.
---
 global/post-tasks.d/018packages | 96 ++++++++++++++++++++++++++++++++++++-----
 1 file changed, 85 insertions(+), 11 deletions(-)

diff --git a/global/post-tasks.d/018packages b/global/post-tasks.d/018packages
index 9e25e69..bf7bf64 100755
--- a/global/post-tasks.d/018packages
+++ b/global/post-tasks.d/018packages
@@ -1,16 +1,90 @@
-#!/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}
+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 pattern; 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 pattern; 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 "${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 '${pattern:-*}' on puppet-module $module"
+          continue
+        fi
+        git tag -v $TAG &> /dev/null
+        if [ $? == 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
-- 
cgit v1.1