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-----
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-----

View File

@ -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

View File

@ -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

View File

@ -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

26
sig
View File

@ -273,7 +273,7 @@ verify_git(){
[ $# -eq 2 ] || die "Usage: verify_git <threshold> <group>"
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,7 +317,6 @@ verify_git(){
## Get temporary dir reliably across different mktemp implementations
get_temp(){
echo "$(
mktemp \
--quiet \
--directory \
@ -326,7 +324,6 @@ get_temp(){
|| 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
}

View File

@ -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"
}

View File

@ -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(){

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