From 73f696920be0eb754bd6bf46b41ab6317f641fd0 Mon Sep 17 00:00:00 2001 From: Matt Corallo Date: Mon, 27 Oct 2014 00:07:25 -0700 Subject: [PATCH] Add script to verify all merge commits are signed --- contrib/README.md | 9 +++++ contrib/verify-commits/gpg.sh | 15 +++++++ contrib/verify-commits/pre-push-hook.sh | 16 ++++++++ contrib/verify-commits/trusted-git-root | 1 + contrib/verify-commits/trusted-keys | 5 +++ contrib/verify-commits/verify-commits.sh | 51 ++++++++++++++++++++++++ 6 files changed, 97 insertions(+) create mode 100644 contrib/README.md create mode 100755 contrib/verify-commits/gpg.sh create mode 100755 contrib/verify-commits/pre-push-hook.sh create mode 100644 contrib/verify-commits/trusted-git-root create mode 100644 contrib/verify-commits/trusted-keys create mode 100755 contrib/verify-commits/verify-commits.sh diff --git a/contrib/README.md b/contrib/README.md new file mode 100644 index 0000000..da1fc06 --- /dev/null +++ b/contrib/README.md @@ -0,0 +1,9 @@ +Repository Tools +--------------------- + +### [Developer tools](/contrib/devtools) ### +Specific tools for developers working on this repository. +Contains the script `github-merge.sh` for merging github pull requests securely and signing them using GPG. + +### [Verify-Commits](/contrib/verify-commits) ### +Tool to verify that every merge commit was signed by a developer using the above `github-merge.sh` script. diff --git a/contrib/verify-commits/gpg.sh b/contrib/verify-commits/gpg.sh new file mode 100755 index 0000000..6b5137e --- /dev/null +++ b/contrib/verify-commits/gpg.sh @@ -0,0 +1,15 @@ +#!/bin/sh +INPUT=$(/dev/null); do + case "$LINE" in "[GNUPG:] VALIDSIG"*) + while read KEY; do + case "$LINE" in "[GNUPG:] VALIDSIG $KEY "*) VALID=true;; esac + done < ./contrib/verify-commits/trusted-keys + esac +done +if ! $VALID; then + exit 1 +fi +echo "$INPUT" | gpg --trust-model always "$@" 2>/dev/null diff --git a/contrib/verify-commits/pre-push-hook.sh b/contrib/verify-commits/pre-push-hook.sh new file mode 100755 index 0000000..607c0ca --- /dev/null +++ b/contrib/verify-commits/pre-push-hook.sh @@ -0,0 +1,16 @@ +#!/bin/bash +if ! [[ "$2" =~ [git@]?[www.]?github.com[:|/]bitcoin/bitcoin[.git]? ]]; then + exit 0 +fi + +while read LINE; do + set -- A $LINE + if [ "$4" != "refs/heads/master" ]; then + continue + fi + if ! ./contrib/verify-commits/verify-commits.sh $3 > /dev/null 2>&1; then + echo "ERROR: A commit is not signed, can't push" + ./contrib/verify-commits/verify-commits.sh + exit 1 + fi +done < /dev/stdin diff --git a/contrib/verify-commits/trusted-git-root b/contrib/verify-commits/trusted-git-root new file mode 100644 index 0000000..eb13f87 --- /dev/null +++ b/contrib/verify-commits/trusted-git-root @@ -0,0 +1 @@ +053038e5ba116cb319fb85f3cb3e062cf1b3df15 diff --git a/contrib/verify-commits/trusted-keys b/contrib/verify-commits/trusted-keys new file mode 100644 index 0000000..658ad03 --- /dev/null +++ b/contrib/verify-commits/trusted-keys @@ -0,0 +1,5 @@ +71A3B16735405025D447E8F274810B012346C9A6 +1F4410F6A89268CE3197A84C57896D2FF8F0B657 +01CDF4627A3B88AAE4A571C87588242FBE38D3A8 +AF8BE07C7049F3A26B239D5325B3083201782B2F +81291FA67D2C379A006A053FEAB5AF94D9E9ABE7 diff --git a/contrib/verify-commits/verify-commits.sh b/contrib/verify-commits/verify-commits.sh new file mode 100755 index 0000000..5841fa2 --- /dev/null +++ b/contrib/verify-commits/verify-commits.sh @@ -0,0 +1,51 @@ +#!/bin/sh + +DIR=$(dirname "$0") + +echo "Please verify all commits in the following list are not evil:" +git log "$DIR" + +VERIFIED_ROOT=$(cat "${DIR}/trusted-git-root") + +HAVE_FAILED=false +IS_SIGNED () { + if [ $1 = $VERIFIED_ROOT ]; then + return 0; + fi + if ! git -c "gpg.program=${DIR}/gpg.sh" verify-commit $1 > /dev/null 2>&1; then + return 1; + fi + local PARENTS=$(git show -s --format=format:%P $1) + for PARENT in $PARENTS; do + if IS_SIGNED $PARENT > /dev/null; then + return 0; + fi + done + if ! "$HAVE_FAILED"; then + echo "No parent of $1 was signed with a trusted key!" > /dev/stderr + echo "Parents are:" > /dev/stderr + for PARENT in $PARENTS; do + git show -s $PARENT > /dev/stderr + done + HAVE_FAILED=true + fi + return 1; +} + +if [ x"$1" = "x" ]; then + TEST_COMMIT="HEAD" +else + TEST_COMMIT="$1" +fi + +IS_SIGNED "$TEST_COMMIT" +RES=$? +if [ "$RES" = 1 ]; then + if ! "$HAVE_FAILED"; then + echo "$TEST_COMMIT was not signed with a trusted key!" + fi +else + echo "There is a valid path from $TEST_COMMIT to $VERIFIED_ROOT where all commits are signed!" +fi + +exit $RES