overhaul git handling to have same threshold meaning as detached using hybrid tag/commit sigs

This commit is contained in:
Lance Vick 2020-12-03 20:56:38 -08:00
parent 37520941a1
commit 890bfd0821
Signed by: lrvick
GPG Key ID: 8E47A1EC35A1551D
8 changed files with 60 additions and 81 deletions

View File

@ -1,16 +1,16 @@
-----BEGIN PGP SIGNATURE----- -----BEGIN PGP SIGNATURE-----
iQIzBAABCgAdFiEEZ1U/vaRrtxq9LgsLjkeh7DWhVR0FAl+9voEACgkQjkeh7DWh iQIzBAABCgAdFiEEZ1U/vaRrtxq9LgsLjkeh7DWhVR0FAl/JwSgACgkQjkeh7DWh
VR1oSg//X/RqCuceOFQdn8HfC24P8mFuHgFFJpdcVDZALLrXek9QuBd++3VSQBPq VR0lcg/+KDAK8wA6y7N836Aq3Q1peXBa6efu9V9I4bZjDPNTx2Yc0VHv7gh8pHtT
ID26OWh0644BOZDNOXkNvYVnyrwc27CAxjWpbQkn8Z+vl/tpO+A7BTSVxS7M70ID 24amY1wfFfLBPBk9ZIPQXeIkHyLjofzCGm9AVufJiwvF+vII9I+WEKAZgStQ08mZ
krxi78nZGgatMsZMWzsPvWe8UCzMd4EN92AUhXGCdU2iSSUeHBz4LEJ46QjnAwq9 dnnnXM01zN8AC4+drwGeNHCbVnsvOxOkUe0YJeyR8u0N1H04xSBkgOb3jYDgDiNH
dda+mo7qvYLcLcGZJcdrjKTdgquDi83eUkCvB5tI+SJsdRrQED9sEjAQW/rwVs1p e21ZnqqPru1jsa8mk9ddXXUwbz0HU/GJ65Pls99EXx6oVuYAKgWCiUQDtFNwWx1C
eh1riIJ7ooG0s1SGWT25tn7Z8Xm91mV7GjcbG+PZJUFdcmwouV9lqc0Kzx/6sxvO G4QmoQqD4q8Pwq2Hmgn4RUf+HmUvN9cKXy6IFBEcscbQJkfMSUzruYi/3sfM+vwJ
veD68TasBcDvn3HfOVrM641HuXVqLPwDWq+eZz8WdhfNj6fKF0u5325XKKfDBIsH hrQuzODY7iRSI8ktaFeDEe55GX8CFfWdPoxSLCrn86ZfsExGeRv3c4J6/6NYmt2R
uro3AuE/t1KkAnPcYUQXh3lhG/aY6Xddgy7JJ2ZwaiV6jV17XoNKfstjrEGkBgRc uNCKSLAENTRyCl9zP2/usxSX1Aw2v3Mx8qSYUWIcus8jxCotDD6vh7xFqlbX0gXD
BZmAX4dtVK6VLcnoZC16DBFicn7EwCKO1eoSJD7n+3kPH9TbcwD9134g3GJDzif/ dVOnL2Im3kS1VLIBhP6hefrh43vZbxMSzjQcF2xgBGeHyGxd5QumiFjm/ZUGEHWq
n7PGPEtinO0lGRUbtr3QO73eaV2IaGvc/d0e7zzHq1gyaMOycTAxouSe8ePaJVn5 yvIF7M5PpO9h3elqSEnjsL4fDX7sLkiVg7nVsG40d7QAAg9puw2XhFIkQNpAMJuc
iQkqSr/dcgHNL7XA/o39V2CWuC2Tx5UtRKJusJNQhM92Sn9lcAfTz1U6L0nZj4uk oW3p6b4TOioSSFE7s+AlyiT7IInRajE4XnJYly+N1wBMYPfaowpVym7iQxdbj3DL
SKShEww86RLSj07jGfcgHjEXPQ5WZ5qmizsxJyXOITpR2wV1FmM= UqBtR2gkM1/JoRy+EGC/OnZhHmUEy8ZbiLz6esWf7PpgXU6oRuI=
=jgfL =wmMj
-----END PGP SIGNATURE----- -----END PGP SIGNATURE-----

View File

@ -1,8 +1,8 @@
64263feac7b00952e9ec3b6c1fd11316faa58ff673c6bd085fac9f6f8d8389f6 .gitignore 64263feac7b00952e9ec3b6c1fd11316faa58ff673c6bd085fac9f6f8d8389f6 .gitignore
67377eee89dfc4411665474ac0bee0f9a19ea7e594bcc8606b0bc3ace69f0aa1 .gitlab-ci.yml 67377eee89dfc4411665474ac0bee0f9a19ea7e594bcc8606b0bc3ace69f0aa1 .gitlab-ci.yml
ad3d473c630217dff7c4499efc1de46fc3a55068677c2bb3a21714aa56dd408a Makefile 5b4cc41adde64e353d714d02a68ad137ae16b56c086b6e57f228e05157a630f3 Makefile
7d6ada59fb41657c84b9fed7984a0e763d58c1fa851bf306db50f686eebdfbdd README.md 18c1fc760e623b37a6a6e1662c06acfe0712c95ba3cc5d7a568294ef2f8fc7a7 README.md
e6517003db9161086c31e8fc21184273a1e66d536bf628739eae7118052c9be8 sig 2c7e6cc19b3366d5cbf41bfb0d941488403bcb0c4f804cbe38a96434b6846261 sig
646a6c11ef22d51bd7fadff5ecc806d8d3e7c62151a0dd56bbeb59eca74c671c test/Dockerfile 646a6c11ef22d51bd7fadff5ecc806d8d3e7c62151a0dd56bbeb59eca74c671c test/Dockerfile
dd79ef0e6d0738321f916a5c85a60d44152fb1ffcd71572de98cf48e0d0d911c test/keys/user1.pub.asc dd79ef0e6d0738321f916a5c85a60d44152fb1ffcd71572de98cf48e0d0d911c test/keys/user1.pub.asc
c98a656738f188f650fa0107e3478d640c175a3db481a6c3cbc267f75a05b440 test/keys/user1.sec.asc c98a656738f188f650fa0107e3478d640c175a3db481a6c3cbc267f75a05b440 test/keys/user1.sec.asc
@ -14,5 +14,6 @@ c0e3df63b1f01a83e17c463af9e37365a5e38ee0289d59cdfee725df202a311b test/keys/user3
d4cbeffdbf7064aaffe94556b5879c88cddf479e3e76518f25c3491482abd789 test/keys/user4.sec.asc d4cbeffdbf7064aaffe94556b5879c88cddf479e3e76518f25c3491482abd789 test/keys/user4.sec.asc
c608e63175a1e9cc3fe2500372769a9e30b808d2e4d4a950796d98dac14775ea test/keys/user5.pub.asc c608e63175a1e9cc3fe2500372769a9e30b808d2e4d4a950796d98dac14775ea test/keys/user5.pub.asc
873f3a1e2da41587f4b5a0dad5d8b704a37144e54931fe3a167ea9648772a5dc test/keys/user5.sec.asc 873f3a1e2da41587f4b5a0dad5d8b704a37144e54931fe3a167ea9648772a5dc test/keys/user5.sec.asc
8a517fceb28c7afe5c6baba7792f5f914310800b7ddfde8d3265e26ab46cbee7 test/test.bats 7d1614e83e0c7ebeaf75cc6ccea06277d29a1af0a049b1127c7e05cdd189c4c5 test/test.bats
418903b58dad935ee3aa1dfcc4c4ac22fd77a838b87a5c2c3fe4e510a164f0a0 test/test_helper.bash 28fd19a494f0bda68eece78e13c60a819cc75df77b5da14fbf9f341193d56f92 test/test_helper.bash
a8422089d91aa3c4220221ff9e115a9e1d914d7d53eaac533a70449ef63d7f6d test/test_shell.bash

View File

@ -49,4 +49,4 @@ test-shell: test-image
--interactive \ --interactive \
--volume $(PWD)/:/home/test/sig \ --volume $(PWD)/:/home/test/sig \
local/sig-test \ local/sig-test \
bash bash --init-file /home/test/sig/test/test_shell.bash

View File

@ -69,38 +69,31 @@ The simple GPG signature toolchain for directories or git repos.
### Git ### 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 This counts the commit signature, and any number of signed tags pointing at
are found to satisify the threshold, ensuring all commits between are signed. this ref.
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
### Detached ### Detached
This method verifies the state of this folder was signed exactly as-is by one This method verifies the state of this folder was signed exactly as-is by one
or more authors. or more authors.
## Behavior
If 'threshold' is specified, then that number of signatures must be present. 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 If 'group' is specified, all signatures must be by keys that belong to a
defined gpg alias group. defined gpg alias group.
#### Assumptions ### Assumptions
- Single sig mode: Folder contents controlled by signer - Single sig mode: Folder contents controlled by signer
- Multi-sig mode: Folder contents verified by multiple signers - Multi-sig mode: Folder contents verified by multiple signers
- Multi-sig group mode: Folder contents approved by specified individuals - 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 ## Examples

26
sig
View File

@ -273,7 +273,7 @@ verify_git(){
[ $# -eq 2 ] || die "Usage: verify_git <threshold> <group>" [ $# -eq 2 ] || die "Usage: verify_git <threshold> <group>"
local -r threshold="${1}" local -r threshold="${1}"
local -r group="${2}" 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 \ git verify-commit HEAD >/dev/null 2>&1 \
|| die "HEAD commit not signed" || die "HEAD commit not signed"
@ -287,12 +287,11 @@ verify_git(){
for tag in $(git tag --points-at HEAD); do for tag in $(git tag --points-at HEAD); do
git tag --verify "$tag" >/dev/null 2>&1 && { git tag --verify "$tag" >/dev/null 2>&1 && {
fp=$( \ fp=$( \
git verify-tag --raw extra-sig 2>&1 \ git verify-tag --raw "$tag" 2>&1 \
| grep VALIDSIG \ | grep VALIDSIG \
| sed 's/.*VALIDSIG \([A-Z0-9]\+\).*/\1/g' \ | sed 's/.*VALIDSIG \([A-Z0-9]\+\).*/\1/g' \
) )
uid=$( get_uid "${fp}" ) uid=$( get_uid "${fp}" )
seen_fps="${seen_fps} ${fp}"
if [[ "${seen_fps}" != *"${fp}"* ]]; then if [[ "${seen_fps}" != *"${fp}"* ]]; then
seen_fps="${seen_fps} ${fp}" seen_fps="${seen_fps} ${fp}"
echo "Verified signed git tag by \"${uid}\"" echo "Verified signed git tag by \"${uid}\""
@ -307,8 +306,8 @@ verify_git(){
} }
if [ ! -z "$group" ]; then if [ ! -z "$group" ]; then
for fp in "${seen_fps}"; do for seen_fp in ${seen_fps}; do
group_check_fp "${fp}" "${group}" || { group_check_fp "${seen_fp}" "${group}" || {
echo "Git signing key not in group \"${group}\": ${fp}"; echo "Git signing key not in group \"${group}\": ${fp}";
return 1; return 1;
} }
@ -318,7 +317,6 @@ verify_git(){
## Get temporary dir reliably across different mktemp implementations ## Get temporary dir reliably across different mktemp implementations
get_temp(){ get_temp(){
echo "$(
mktemp \ mktemp \
--quiet \ --quiet \
--directory \ --directory \
@ -326,7 +324,6 @@ get_temp(){
|| mktemp \ || mktemp \
--quiet \ --quiet \
--directory --directory
)"
} }
@ -343,7 +340,6 @@ verify_git_diff(){
local -r temp_repo=$(get_temp) local -r temp_repo=$(get_temp)
local -r git_root=$(git rev-parse --show-toplevel) local -r git_root=$(git rev-parse --show-toplevel)
local -r curr_ref=$(git rev-parse HEAD) local -r curr_ref=$(git rev-parse HEAD)
set -x
cp -a "${git_root}/." "${temp_repo}/" cp -a "${git_root}/." "${temp_repo}/"
cd "${temp_repo}" cd "${temp_repo}"
git reset --hard "${diff_ref}" >/dev/null 2>&1 git reset --hard "${diff_ref}" >/dev/null 2>&1
@ -352,7 +348,6 @@ verify_git_diff(){
else else
echo "Verification of specifed diff ref failed: ${ref}" echo "Verification of specifed diff ref failed: ${ref}"
fi fi
set +x
} }
## Verify current folder/repo with specified signing rules ## Verify current folder/repo with specified signing rules
@ -406,14 +401,14 @@ sign_tag(){
git config --get user.signingKey >/dev/null \ git config --get user.signingKey >/dev/null \
|| die "Git user.signingKey not set" || die "Git user.signingKey not set"
local -r push="${1}" local -r push="${1}"
local -r short_hash=$(git rev-parse --short HEAD) local -r commit=$(git rev-parse --short HEAD)
local -r signing_fp=$( \ local -r fp=$( \
git config --get user.signingKey \ git config --get user.signingKey \
| sed 's/.*\([A-Z0-9]\{16\}\).*/\1/g' \ | 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" 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() { cmd_verify() {
local opts threshold=1 group="" method="" diff="" local opts threshold=1 group="" method="" diff=""
local -r args="$@"
opts="$(getopt -o t:g:m:d: -l threshold:,group:,method:,diff: -n "$PROGRAM" -- "$@")" opts="$(getopt -o t:g:m:d: -l threshold:,group:,method:,diff: -n "$PROGRAM" -- "$@")"
eval set -- "$opts" eval set -- "$opts"
while true; do case $1 in while true; do case $1 in
@ -495,7 +489,6 @@ cmd_fetch() {
cmd_add(){ cmd_add(){
local opts method="default" push=0 local opts method="default" push=0
local -r args="$@"
opts="$(getopt -o m:p:: -l method:push:: -n "$PROGRAM" -- "$@")" opts="$(getopt -o m:p:: -l method:push:: -n "$PROGRAM" -- "$@")"
eval set -- "$opts" eval set -- "$opts"
while true; do case $1 in while true; do case $1 in
@ -513,8 +506,7 @@ cmd_add(){
;; ;;
detached) sign_detached ;; detached) sign_detached ;;
git) sign_tag "$push" ;; git) sign_tag "$push" ;;
*) cmd_help ;; *) cmd_usage ;;
--) shift; break ;;
esac esac
} }

View File

@ -81,13 +81,10 @@ load test_helper
git add . git add .
git commit -m "user1 commit" git commit -m "user1 commit"
set_identity "user2" set_identity "user2"
echo "test string 2" > somefile2 git log
git add . sig add
git commit -m "user2 commit"
set_identity "user3" set_identity "user3"
echo "test string 3" > somefile3 sig add
git add .
git commit -m "user3 commit"
run sig verify --method git --threshold 3 run sig verify --method git --threshold 3
[ "$status" -eq 0 ] [ "$status" -eq 0 ]
} }
@ -120,15 +117,9 @@ load test_helper
git add . git add .
git commit -m "User 1 Commit" git commit -m "User 1 Commit"
set_identity "user2" set_identity "user2"
echo "test string" > somefile2 sig add
git init
git add .
git commit -m "User 2 Commit"
set_identity "user3" set_identity "user3"
echo "test string" > somefile3 sig add
git init
git add .
git commit -m "User 3 Commit"
sig fetch --group maintainers AE08157232C35F04309FA478C5EBC4A7CF55A2D0 sig fetch --group maintainers AE08157232C35F04309FA478C5EBC4A7CF55A2D0
sig fetch --group maintainers BE4D60F6CFD2237A8AF978583C51CADD33BD0EE8 sig fetch --group maintainers BE4D60F6CFD2237A8AF978583C51CADD33BD0EE8
sig fetch --group maintainers 3E45AC9E190B4EE32BAE9F61A331AFB540761D69 sig fetch --group maintainers 3E45AC9E190B4EE32BAE9F61A331AFB540761D69
@ -203,23 +194,19 @@ load test_helper
set_identity "user1" set_identity "user1"
echo "test string" > testfile echo "test string" > testfile
sig add
git add . git add .
git commit -m "User 1 Commit" git commit -m "User 1 Commit"
set_identity "user2" set_identity "user2"
sig add sig add
git add .
git commit -m "User 2 Commit"
set_identity "user1" set_identity "user1"
git checkout -b feature_branch git checkout -b feature_branch
echo "updated test string" > somefile1 echo "updated test string" > somefile1
sig add
git add . git add .
git commit -m "User 1 Update Commit" 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 ] [ "$status" -eq 1 ]
echo "${output}" | grep "updated test string" echo "${output}" | grep "updated test string"
} }

View File

@ -8,12 +8,12 @@ setup(){
bin_dir=/tmp/bin bin_dir=/tmp/bin
temp_dir=$(mktemp -d -t test-XXXXXXXXXX) temp_dir=$(mktemp -d -t test-XXXXXXXXXX)
mkdir -p /tmp/bin 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} export PATH=${bin_dir}:${PATH}
cd "$temp_dir" || return 1 cd "$temp_dir" || return 1
rm -rf ~/.gnupg rm -rf ~/.gnupg
rm -rf ~/.gitconfig rm -rf ~/.gitconfig
killall gpg-agent || : killall gpg-agent >/dev/null 2>&1 || :
} }
teardown(){ teardown(){

6
test/test_shell.bash Normal file
View File

@ -0,0 +1,6 @@
#!/bin/bash
source /home/test/sig/test/test_helper.bash
setup
eval "$(declare -F | sed -e 's/-f /-fx /')"
bash