overhaul git handling to have same threshold meaning as detached using hybrid tag/commit sigs
This commit is contained in:
parent
37520941a1
commit
890bfd0821
|
@ -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-----
|
||||||
|
|
|
@ -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
|
||||||
|
|
2
Makefile
2
Makefile
|
@ -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
|
||||||
|
|
27
README.md
27
README.md
|
@ -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
|
||||||
|
|
||||||
|
|
40
sig
40
sig
|
@ -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,15 +317,13 @@ 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 \
|
-t "$(basename "$0").XXXXXX" 2>/dev/null \
|
||||||
-t "$(basename "$0").XXXXXX" 2>/dev/null \
|
|| 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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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"
|
||||||
}
|
}
|
||||||
|
|
|
@ -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(){
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
source /home/test/sig/test/test_helper.bash
|
||||||
|
setup
|
||||||
|
eval "$(declare -F | sed -e 's/-f /-fx /')"
|
||||||
|
bash
|
Loading…
Reference in New Issue