From 890bfd08214810783be61c4572a9c0acbdd0c363 Mon Sep 17 00:00:00 2001 From: "Lance R. Vick" Date: Thu, 3 Dec 2020 20:56:38 -0800 Subject: [PATCH] overhaul git handling to have same threshold meaning as detached using hybrid tag/commit sigs --- .sig/manifest.8E47A1EC35A1551D.asc | 26 +++++++++---------- .sig/manifest.txt | 11 ++++---- Makefile | 2 +- README.md | 27 ++++++++------------ sig | 40 ++++++++++++------------------ test/test.bats | 25 +++++-------------- test/test_helper.bash | 4 +-- test/test_shell.bash | 6 +++++ 8 files changed, 60 insertions(+), 81 deletions(-) create mode 100644 test/test_shell.bash diff --git a/.sig/manifest.8E47A1EC35A1551D.asc b/.sig/manifest.8E47A1EC35A1551D.asc index b13eb80..c07f357 100644 --- a/.sig/manifest.8E47A1EC35A1551D.asc +++ b/.sig/manifest.8E47A1EC35A1551D.asc @@ -1,16 +1,16 @@ -----BEGIN PGP SIGNATURE----- -iQIzBAABCgAdFiEEZ1U/vaRrtxq9LgsLjkeh7DWhVR0FAl+9voEACgkQjkeh7DWh -VR1oSg//X/RqCuceOFQdn8HfC24P8mFuHgFFJpdcVDZALLrXek9QuBd++3VSQBPq -ID26OWh0644BOZDNOXkNvYVnyrwc27CAxjWpbQkn8Z+vl/tpO+A7BTSVxS7M70ID -krxi78nZGgatMsZMWzsPvWe8UCzMd4EN92AUhXGCdU2iSSUeHBz4LEJ46QjnAwq9 -dda+mo7qvYLcLcGZJcdrjKTdgquDi83eUkCvB5tI+SJsdRrQED9sEjAQW/rwVs1p -eh1riIJ7ooG0s1SGWT25tn7Z8Xm91mV7GjcbG+PZJUFdcmwouV9lqc0Kzx/6sxvO -veD68TasBcDvn3HfOVrM641HuXVqLPwDWq+eZz8WdhfNj6fKF0u5325XKKfDBIsH -uro3AuE/t1KkAnPcYUQXh3lhG/aY6Xddgy7JJ2ZwaiV6jV17XoNKfstjrEGkBgRc -BZmAX4dtVK6VLcnoZC16DBFicn7EwCKO1eoSJD7n+3kPH9TbcwD9134g3GJDzif/ -n7PGPEtinO0lGRUbtr3QO73eaV2IaGvc/d0e7zzHq1gyaMOycTAxouSe8ePaJVn5 -iQkqSr/dcgHNL7XA/o39V2CWuC2Tx5UtRKJusJNQhM92Sn9lcAfTz1U6L0nZj4uk -SKShEww86RLSj07jGfcgHjEXPQ5WZ5qmizsxJyXOITpR2wV1FmM= -=jgfL +iQIzBAABCgAdFiEEZ1U/vaRrtxq9LgsLjkeh7DWhVR0FAl/JwSgACgkQjkeh7DWh +VR0lcg/+KDAK8wA6y7N836Aq3Q1peXBa6efu9V9I4bZjDPNTx2Yc0VHv7gh8pHtT +24amY1wfFfLBPBk9ZIPQXeIkHyLjofzCGm9AVufJiwvF+vII9I+WEKAZgStQ08mZ +dnnnXM01zN8AC4+drwGeNHCbVnsvOxOkUe0YJeyR8u0N1H04xSBkgOb3jYDgDiNH +e21ZnqqPru1jsa8mk9ddXXUwbz0HU/GJ65Pls99EXx6oVuYAKgWCiUQDtFNwWx1C +G4QmoQqD4q8Pwq2Hmgn4RUf+HmUvN9cKXy6IFBEcscbQJkfMSUzruYi/3sfM+vwJ +hrQuzODY7iRSI8ktaFeDEe55GX8CFfWdPoxSLCrn86ZfsExGeRv3c4J6/6NYmt2R +uNCKSLAENTRyCl9zP2/usxSX1Aw2v3Mx8qSYUWIcus8jxCotDD6vh7xFqlbX0gXD +dVOnL2Im3kS1VLIBhP6hefrh43vZbxMSzjQcF2xgBGeHyGxd5QumiFjm/ZUGEHWq +yvIF7M5PpO9h3elqSEnjsL4fDX7sLkiVg7nVsG40d7QAAg9puw2XhFIkQNpAMJuc +oW3p6b4TOioSSFE7s+AlyiT7IInRajE4XnJYly+N1wBMYPfaowpVym7iQxdbj3DL +UqBtR2gkM1/JoRy+EGC/OnZhHmUEy8ZbiLz6esWf7PpgXU6oRuI= +=wmMj -----END PGP SIGNATURE----- diff --git a/.sig/manifest.txt b/.sig/manifest.txt index 4e02fb8..29b3482 100644 --- a/.sig/manifest.txt +++ b/.sig/manifest.txt @@ -1,8 +1,8 @@ 64263feac7b00952e9ec3b6c1fd11316faa58ff673c6bd085fac9f6f8d8389f6 .gitignore 67377eee89dfc4411665474ac0bee0f9a19ea7e594bcc8606b0bc3ace69f0aa1 .gitlab-ci.yml -ad3d473c630217dff7c4499efc1de46fc3a55068677c2bb3a21714aa56dd408a Makefile -7d6ada59fb41657c84b9fed7984a0e763d58c1fa851bf306db50f686eebdfbdd README.md -e6517003db9161086c31e8fc21184273a1e66d536bf628739eae7118052c9be8 sig +5b4cc41adde64e353d714d02a68ad137ae16b56c086b6e57f228e05157a630f3 Makefile +18c1fc760e623b37a6a6e1662c06acfe0712c95ba3cc5d7a568294ef2f8fc7a7 README.md +2c7e6cc19b3366d5cbf41bfb0d941488403bcb0c4f804cbe38a96434b6846261 sig 646a6c11ef22d51bd7fadff5ecc806d8d3e7c62151a0dd56bbeb59eca74c671c test/Dockerfile dd79ef0e6d0738321f916a5c85a60d44152fb1ffcd71572de98cf48e0d0d911c test/keys/user1.pub.asc c98a656738f188f650fa0107e3478d640c175a3db481a6c3cbc267f75a05b440 test/keys/user1.sec.asc @@ -14,5 +14,6 @@ c0e3df63b1f01a83e17c463af9e37365a5e38ee0289d59cdfee725df202a311b test/keys/user3 d4cbeffdbf7064aaffe94556b5879c88cddf479e3e76518f25c3491482abd789 test/keys/user4.sec.asc c608e63175a1e9cc3fe2500372769a9e30b808d2e4d4a950796d98dac14775ea test/keys/user5.pub.asc 873f3a1e2da41587f4b5a0dad5d8b704a37144e54931fe3a167ea9648772a5dc test/keys/user5.sec.asc -8a517fceb28c7afe5c6baba7792f5f914310800b7ddfde8d3265e26ab46cbee7 test/test.bats -418903b58dad935ee3aa1dfcc4c4ac22fd77a838b87a5c2c3fe4e510a164f0a0 test/test_helper.bash +7d1614e83e0c7ebeaf75cc6ccea06277d29a1af0a049b1127c7e05cdd189c4c5 test/test.bats +28fd19a494f0bda68eece78e13c60a819cc75df77b5da14fbf9f341193d56f92 test/test_helper.bash +a8422089d91aa3c4220221ff9e115a9e1d914d7d53eaac533a70449ef63d7f6d test/test_shell.bash diff --git a/Makefile b/Makefile index 1ccb19f..ad2ec32 100644 --- a/Makefile +++ b/Makefile @@ -49,4 +49,4 @@ test-shell: test-image --interactive \ --volume $(PWD)/:/home/test/sig \ local/sig-test \ - bash + bash --init-file /home/test/sig/test/test_shell.bash diff --git a/README.md b/README.md index 0084b86..a980486 100644 --- a/README.md +++ b/README.md @@ -69,38 +69,31 @@ The simple GPG signature toolchain for directories or git repos. ### Git -This method verifies a git repo contains signed commits by one or more authors. +This method verifies the current HEAD was signed exactly as-is by one or more +keys. -If 'threshold' is specified, it searches history until enough unique signatures -are found to satisify the threshold, ensuring all commits between are signed. - -If 'group' is specified, all signatures must be from keys that belong to a -defined gpg alias group. - -Note: this only proves the history had multiple participants, but not that -the current HEAD was verified by all participants. - -#### Assumptions - - Single sig mode: Repo HEAD controlled by signer - - Multi-sig mode: Repo has contributions from multiple individuals - - Multi-sig group mode: Repo has contributions from specified individuals - - Sha1 is not broken +This counts the commit signature, and any number of signed tags pointing at +this ref. ### Detached This method verifies the state of this folder was signed exactly as-is by one or more authors. +## Behavior + If 'threshold' is specified, then that number of signatures must be present. If 'group' is specified, all signatures must be by keys that belong to a defined gpg alias group. -#### Assumptions +### Assumptions - Single sig mode: Folder contents controlled by signer - Multi-sig mode: Folder contents verified by multiple signers - Multi-sig group mode: Folder contents approved by specified individuals - - Sha256 is not broken + - Hashing scheme for respective backend is not broken + - Git: sha1 + - Detached: sha256 ## Examples diff --git a/sig b/sig index 70602f4..1553d52 100755 --- a/sig +++ b/sig @@ -273,7 +273,7 @@ verify_git(){ [ $# -eq 2 ] || die "Usage: verify_git " local -r threshold="${1}" local -r group="${2}" - local seen_fps="" sig_count=0 depth=0 ref commit fp uid + local seen_fps="" sig_count=0 ref commit fp uid git verify-commit HEAD >/dev/null 2>&1 \ || die "HEAD commit not signed" @@ -287,12 +287,11 @@ verify_git(){ for tag in $(git tag --points-at HEAD); do git tag --verify "$tag" >/dev/null 2>&1 && { fp=$( \ - git verify-tag --raw extra-sig 2>&1 \ + git verify-tag --raw "$tag" 2>&1 \ | grep VALIDSIG \ | sed 's/.*VALIDSIG \([A-Z0-9]\+\).*/\1/g' \ ) uid=$( get_uid "${fp}" ) - seen_fps="${seen_fps} ${fp}" if [[ "${seen_fps}" != *"${fp}"* ]]; then seen_fps="${seen_fps} ${fp}" echo "Verified signed git tag by \"${uid}\"" @@ -307,8 +306,8 @@ verify_git(){ } if [ ! -z "$group" ]; then - for fp in "${seen_fps}"; do - group_check_fp "${fp}" "${group}" || { + for seen_fp in ${seen_fps}; do + group_check_fp "${seen_fp}" "${group}" || { echo "Git signing key not in group \"${group}\": ${fp}"; return 1; } @@ -318,15 +317,13 @@ verify_git(){ ## Get temporary dir reliably across different mktemp implementations get_temp(){ - echo "$( - mktemp \ - --quiet \ - --directory \ - -t "$(basename "$0").XXXXXX" 2>/dev/null \ - || mktemp \ - --quiet \ - --directory - )" + mktemp \ + --quiet \ + --directory \ + -t "$(basename "$0").XXXXXX" 2>/dev/null \ + || mktemp \ + --quiet \ + --directory } @@ -343,7 +340,6 @@ verify_git_diff(){ local -r temp_repo=$(get_temp) local -r git_root=$(git rev-parse --show-toplevel) local -r curr_ref=$(git rev-parse HEAD) - set -x cp -a "${git_root}/." "${temp_repo}/" cd "${temp_repo}" git reset --hard "${diff_ref}" >/dev/null 2>&1 @@ -352,7 +348,6 @@ verify_git_diff(){ else echo "Verification of specifed diff ref failed: ${ref}" fi - set +x } ## Verify current folder/repo with specified signing rules @@ -406,14 +401,14 @@ sign_tag(){ git config --get user.signingKey >/dev/null \ || die "Git user.signingKey not set" local -r push="${1}" - local -r short_hash=$(git rev-parse --short HEAD) - local -r signing_fp=$( \ + local -r commit=$(git rev-parse --short HEAD) + local -r fp=$( \ git config --get user.signingKey \ | sed 's/.*\([A-Z0-9]\{16\}\).*/\1/g' \ ) - local -r name="sig-${short_hash}-${signing_fp}" + local -r name="sig-${commit}-${fp}" git tag -fsm "$name" "$name" - [[ $push -eq 1 ]] && git push --tags + [[ $push -eq 0 ]] || git push --tags } @@ -430,7 +425,6 @@ cmd_manifest() { cmd_verify() { local opts threshold=1 group="" method="" diff="" - local -r args="$@" opts="$(getopt -o t:g:m:d: -l threshold:,group:,method:,diff: -n "$PROGRAM" -- "$@")" eval set -- "$opts" while true; do case $1 in @@ -495,7 +489,6 @@ cmd_fetch() { cmd_add(){ local opts method="default" push=0 - local -r args="$@" opts="$(getopt -o m:p:: -l method:push:: -n "$PROGRAM" -- "$@")" eval set -- "$opts" while true; do case $1 in @@ -513,8 +506,7 @@ cmd_add(){ ;; detached) sign_detached ;; git) sign_tag "$push" ;; - *) cmd_help ;; - --) shift; break ;; + *) cmd_usage ;; esac } diff --git a/test/test.bats b/test/test.bats index 23c788c..56a0a71 100644 --- a/test/test.bats +++ b/test/test.bats @@ -81,13 +81,10 @@ load test_helper git add . git commit -m "user1 commit" set_identity "user2" - echo "test string 2" > somefile2 - git add . - git commit -m "user2 commit" + git log + sig add set_identity "user3" - echo "test string 3" > somefile3 - git add . - git commit -m "user3 commit" + sig add run sig verify --method git --threshold 3 [ "$status" -eq 0 ] } @@ -120,15 +117,9 @@ load test_helper git add . git commit -m "User 1 Commit" set_identity "user2" - echo "test string" > somefile2 - git init - git add . - git commit -m "User 2 Commit" + sig add set_identity "user3" - echo "test string" > somefile3 - git init - git add . - git commit -m "User 3 Commit" + sig add sig fetch --group maintainers AE08157232C35F04309FA478C5EBC4A7CF55A2D0 sig fetch --group maintainers BE4D60F6CFD2237A8AF978583C51CADD33BD0EE8 sig fetch --group maintainers 3E45AC9E190B4EE32BAE9F61A331AFB540761D69 @@ -203,23 +194,19 @@ load test_helper set_identity "user1" echo "test string" > testfile - sig add git add . git commit -m "User 1 Commit" set_identity "user2" sig add - git add . - git commit -m "User 2 Commit" set_identity "user1" git checkout -b feature_branch echo "updated test string" > somefile1 - sig add git add . git commit -m "User 1 Update Commit" - run sig verify --diff master --method detached --threshold 2 + run sig verify --diff master --threshold 2 [ "$status" -eq 1 ] echo "${output}" | grep "updated test string" } diff --git a/test/test_helper.bash b/test/test_helper.bash index f59bb2e..0e88225 100644 --- a/test/test_helper.bash +++ b/test/test_helper.bash @@ -8,12 +8,12 @@ setup(){ bin_dir=/tmp/bin temp_dir=$(mktemp -d -t test-XXXXXXXXXX) mkdir -p /tmp/bin - cp /home/test/sig/sig /tmp/bin/sig + ln -sfn /home/test/sig/sig /tmp/bin/sig export PATH=${bin_dir}:${PATH} cd "$temp_dir" || return 1 rm -rf ~/.gnupg rm -rf ~/.gitconfig - killall gpg-agent || : + killall gpg-agent >/dev/null 2>&1 || : } teardown(){ diff --git a/test/test_shell.bash b/test/test_shell.bash new file mode 100644 index 0000000..66b8448 --- /dev/null +++ b/test/test_shell.bash @@ -0,0 +1,6 @@ +#!/bin/bash + +source /home/test/sig/test/test_helper.bash +setup +eval "$(declare -F | sed -e 's/-f /-fx /')" +bash