diff --git a/.sig/manifest.8E47A1EC35A1551D.asc b/.sig/manifest.8E47A1EC35A1551D.asc index fc6d266..8cc9be0 100644 --- a/.sig/manifest.8E47A1EC35A1551D.asc +++ b/.sig/manifest.8E47A1EC35A1551D.asc @@ -1,16 +1,16 @@ -----BEGIN PGP SIGNATURE----- -iQIzBAABCgAdFiEEZ1U/vaRrtxq9LgsLjkeh7DWhVR0FAl+vL3cACgkQjkeh7DWh -VR3pXg//edF6tpvIaIcVhe72Wg/NOnz277brPdFnpnZTi9kZOanrPilyMJ5ahTVP -Au+Z/3LX470ewUTpN9DP1ou5yEMyHYE6nq2UDVhmrmxz5WnydqfibuTX1gmIj1RP -xctTus0Q9KIA2YOyEa5LQ30DyKzNb3uMbhEbu/Px1FciuvQTP2kzusUEgLI2HBPJ -fH05M6W2ppYslHZDRf3lc1D6z72f4IpwedkHHq/8ilbIWwmasayYDqr1Smddnz7i -e/ysFhDq3C3/tljS0IxS1U7r3O7NqL49bBixTg/fPo2iTH/3GgnBuYQoDxxMXlRV -fTT7xhlAfK3PewYwIjPBx14TCe+omU95okhbwBWVw5Zh8KxRlWdjS0X0zrZW21JQ -RJeCEmH0QJKur9CzD86AXkDj9GSIQDdaVaD4w5f+BRaboroxRF+n3yhRaDYdVbYf -Uqwn09NyNV8GrGjQMTBaDaMiXvdrvScPRQcJkL54gwzCsrzpl8Bvj8eX9ESH5tw6 -b8xCY6YMn8SwivC2DlDXB6q9DU7i41xinupMoivyBLkR7G69tZL/n7pc0syjj9UH -v1HyyGG6sski1/8cTvi3Q+Oo6kx7OGLZ8K3rpmORYkT+m3SxTYQgFwLHoubO4c7Q -J5rlMmWM3n8E1fcx4Cri0jI+1IZGS7FSFQxzo7x4U3s3yGbLmPI= -=n932 +iQIzBAABCgAdFiEEZ1U/vaRrtxq9LgsLjkeh7DWhVR0FAl+yVvEACgkQjkeh7DWh +VR1qXA//Vy4EGUfGi4KkzWjQuJhuucFReok5h3uKjceqF6Axwf6DME9fB3BDITe2 +4m1MU+MzKpf69k/DEoG/6kANF9aRYjw/ZgczIPTTj6E07F9OEUQRbV58uSACr9OV +XXec8muyWP5LK4SfnbBHAdvQBwIZdeVTDeT/a5I5w11RvGPnw8SOx9vXhH86QasE +Wk2xQ93E5r39zfWxShtH+KPSBksWPkZYVaP2rQTmhg21/yxzRpqj96S3pkaC//8+ +nHmEH5DQHv/80+0zIYLiEJkTkse5FFYGgwpUBA6tTpFUJUQhR2ht958GcLftBkAG +0aY85m3QsCT2Rrq4ayqRcrU/uK7g0ekOAMpJpvBUJl7ksZwE9Fxo2J+h9ruBesc1 +nkAMlUzbvXCFSUX77MTuyfOr9vwURziKHdk699G5nf2H8V8ZcuJnocdX45Sj81SU +SWR6RcNDOcEdKVVvluUEzGYHzuG2uEpx5ja+vWzUW1fkrBnHems/uNTvdIoehm6Y +H5RKrgn6SXAhUtA8OfSUx9U+woWU1dCT7C4L8a6nM2u3QTI8hkTHiEVQzau7+d6B +Cu31iLamRXo+Kp7rmFSyrGouzhF1jRWAMwJZl80GpWcHjSYzvbEzpp4Zngb8Nm0S +qu3j61unUGcMZNUAjhF04adQQ2Wcp7U5xA/aMZGfN8aJEtDKMC4= +=9AUa -----END PGP SIGNATURE----- diff --git a/.sig/manifest.txt b/.sig/manifest.txt index 43f914c..9ab5447 100644 --- a/.sig/manifest.txt +++ b/.sig/manifest.txt @@ -1,2 +1,2 @@ 64263feac7b00952e9ec3b6c1fd11316faa58ff673c6bd085fac9f6f8d8389f6 .gitignore -e008111dff82be23ab7999b0938e9fffb2fd4826d99f87ed5d0a70256fd43908 sig +592bb0c186797cc93e3e1eb4c58ceb420b9c36f72521f71da49a05c6452e95e6 sig diff --git a/sig b/sig index e0584bd..093e03a 100755 --- a/sig +++ b/sig @@ -6,11 +6,15 @@ MIN_GPG_VERSION=2.2 MIN_OPENSSL_VERSION=1.1 MIN_GETOPT_VERSION=2.33 +## Private Functions + +### Bail with error message die() { echo "$@" >&2 exit 1 } +### Bail and instruct user on missing package to install for their platform die_pkg() { local package=${1?} local version=${2?} @@ -36,6 +40,7 @@ die_pkg() { exit 1 } +### Check if actual binary version is >= minimum version check_version(){ local pkg="${1?}" local have="${2?}" @@ -53,6 +58,7 @@ check_version(){ done } +### Check if required binaries are installed at appropriate versions check_tools(){ if [ -z "${BASH_VERSINFO}" ] \ || [ -z "${BASH_VERSINFO[0]}" ] \ @@ -78,6 +84,7 @@ check_tools(){ done } +### Handle different implementations of mktemp across platforms get_temp(){ echo "$( mktemp \ @@ -90,6 +97,8 @@ get_temp(){ )" } +### Get files that will be added to the manifest for signing +### Use git if available, else fall back to find get_files(){ if command -v git >/dev/null; then git ls-files | grep -v ".${PROGRAM}" @@ -101,6 +110,8 @@ get_files(){ fi } +### Verify a file has 0-N unique valid detached signatures +### Optionally verify all signatures belong to keys in gpg alias group verify_file() { [ $# -eq 3 ] || die "Usage: verify_file " local threshold="${1}" @@ -112,10 +123,12 @@ verify_file() { local fingerprint local signer - [ ! -z "$group" ] && group_config="$( \ - gpg --with-colons --list-config group \ - | grep -i "^cfg:group:${group}:" \ - )" || die "Error: group \"${group}\" not found in ~/.gnupg/gpg.conf" + if [ ! -z "$group" ]; then + group_config="$( \ + gpg --with-colons --list-config group \ + | grep -i "^cfg:group:${group}:" \ + )" || die "Error: group \"${group}\" not found in ~/.gnupg/gpg.conf" + fi for sig_filename in "${filename%.*}".*.asc; do gpg --verify "${sig_filename}" "${filename}" >/dev/null 2>&1 || { @@ -153,18 +166,32 @@ verify_file() { } } +### Verify all commits in git repo have valid signatures +### Optionally verify a minimum number of valid unique signatures +### Optionally verify all signatures belong to keys in gpg alias group +verify_git(){ + [ $# -eq 2 ] || die "Usage: verify_git " + local threshold="${1}" + local group="${2}" + #for commit in $(git log --format='%H%GP'); do + # echo "$commit" + #done +} + + +## Public Commands + cmd_manifest() { mkdir -p ".${PROGRAM}" printf "$(get_files | xargs openssl sha256 -r)" \ - | sed -e 's/ \*/ /g' -e 's/ \.\// /g' \ - | LC_ALL=C sort -k2 \ - > ".${PROGRAM}/manifest.txt" + | sed -e 's/ \*/ /g' -e 's/ \.\// /g' \ + | LC_ALL=C sort -k2 \ + > ".${PROGRAM}/manifest.txt" } cmd_verify() { - local opts selected_line min=1 group="" + local opts min=1 group="" opts="$(getopt -o m:g: -l min:,group: -n "$PROGRAM" -- "$@")" - local err=$? eval set -- "$opts" while true; do case $1 in -m|--min) min="$2"; shift 2 ;; @@ -172,7 +199,10 @@ cmd_verify() { --) shift; break ;; esac done - #TODO: if git: show git signature status to aid in trust building + command -v git >/dev/null 2>&1 \ + && ( [ -d .git ] || git rev-parse --git-dir > /dev/null 2>&1 ) \ + && verify_git "${min}" "${group}" + #TODO: if git and if invalid: show diff against last valid version ( [ -d ".${PROGRAM}" ] && ls .${PROGRAM}/*.asc >/dev/null 2>&1 ) \ || die "Error: No signatures" @@ -208,7 +238,7 @@ cmd_usage() { cat <<-_EOF Usage: $PROGRAM verify [--group=,-g ] [--min=,-m ] - Verify all signing policies for this directory are met + Verify m-of-n signatures by given group are present for directory $PROGRAM add Add signature to manifest for this directory $PROGRAM manifest @@ -220,9 +250,13 @@ cmd_usage() { _EOF } +# Verify all tools in this list are installed at needed versions check_tools head cut find sort sed getopt gpg openssl +# Allow entire script to be namespaced based on filename PROGRAM="${0##*/}" + +# Export public sub-commands case "$1" in verify) shift; cmd_verify "$@" ;; add) shift; cmd_add "$@" ;;